[2160]the implementation of vtn app and modify vtnrsc/pom.xml

Change-Id: I7ce14e3b83a6fa54a6cdb55f1f486aa51038ec01
diff --git a/apps/vtn/pom.xml b/apps/vtn/pom.xml
index aa92717..56aa99d 100644
--- a/apps/vtn/pom.xml
+++ b/apps/vtn/pom.xml
@@ -37,5 +37,10 @@
             <artifactId>onos-core-serializers</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-vtnrsc</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/apps/vtn/src/main/java/org/onosproject/app/vtn/VTNService.java b/apps/vtn/src/main/java/org/onosproject/vtn/VTNService.java
similarity index 97%
rename from apps/vtn/src/main/java/org/onosproject/app/vtn/VTNService.java
rename to apps/vtn/src/main/java/org/onosproject/vtn/VTNService.java
index 880f2b9..a20f852 100644
--- a/apps/vtn/src/main/java/org/onosproject/app/vtn/VTNService.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/VTNService.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.app.vtn;
+package org.onosproject.vtn;
 
 import org.onosproject.net.Device;
 import org.onosproject.net.Host;
diff --git a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
new file mode 100644
index 0000000..6904761
--- /dev/null
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
@@ -0,0 +1,523 @@
+/*
+ * 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.vtn.impl;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.app.vtnrsc.SegmentationId;
+import org.onosproject.app.vtnrsc.TenantNetwork;
+import org.onosproject.app.vtnrsc.VirtualPort;
+import org.onosproject.app.vtnrsc.VirtualPortId;
+import org.onosproject.app.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.app.vtnrsc.virtualport.VirtualPortService;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeName;
+import org.onosproject.net.behaviour.DefaultTunnelDescription;
+import org.onosproject.net.behaviour.IpTunnelEndPoint;
+import org.onosproject.net.behaviour.TunnelConfig;
+import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.net.behaviour.TunnelEndPoint;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtn.VTNService;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of VTNService.
+ */
+@Component(immediate = true)
+@Service
+public class VTNManager implements VTNService {
+    private final Logger log = getLogger(getClass());
+
+    private static final String APP_ID = "org.onosproject.app.vtn";
+    private ScheduledExecutorService backgroundService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected HostService hostService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowRuleService flowRuleService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TenantNetworkService tenantNetworkService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VirtualPortService virtualPortService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowObjectiveService flowObjectiveService;
+    private EventuallyConsistentMap<HostId, SegmentationId> binding;
+    private ApplicationId appId;
+    private HostListener hostListener = new InnerHostListener();
+    private DeviceListener deviceListener = new InnerDeviceListener();
+    private static final String IFACEID = "ifaceid";
+    private static final String PORT_HEAD = "vxlan";
+    private static final int MAC_TABLE = 40;
+    private static final short ETH_TYPE_MAC = 40;
+    private static final short ETH_TYPE_PORT = 0;
+    private static final String DEFAULT_BRIDGE_NAME = "br-int";
+    private static final String CONTROLLER_IP_KEY = "ipaddress";
+
+    @Activate
+    public void activate() {
+        KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+                .register(KryoNamespaces.API);
+        appId = coreService.registerApplication(APP_ID);
+        deviceService.addListener(deviceListener);
+        hostService.addListener(hostListener);
+        backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos-apps/vtn",
+                                                                            "manager-background"));
+        binding = storageService
+                .<HostId, SegmentationId>eventuallyConsistentMapBuilder()
+                .withName("all_tunnel").withSerializer(serializer)
+                .withTimestampProvider((k, v) -> new WallClockTimestamp())
+                .build();
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        backgroundService.shutdown();
+        binding.destroy();
+        log.info("Stopped");
+    }
+
+    @Override
+    public void onServerDetected(Device device) {
+        Iterable<Device> devices = deviceService.getAvailableDevices();
+        DriverHandler handler = driverService.createHandler(device.id());
+        TunnelConfig config = handler.behaviour(TunnelConfig.class);
+        BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+        bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
+        String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
+        IpAddress ip = IpAddress.valueOf(ipAddress);
+        TunnelEndPoint tunnelAsSrcSrc = IpTunnelEndPoint.ipTunnelPoint(ip);
+        TunnelEndPoint tunnelAsDstDst = IpTunnelEndPoint.ipTunnelPoint(ip);
+        devices.forEach(d -> {
+            if (!device.id().equals(d.id())) {
+                String ipAddress1 = d.annotations().value(CONTROLLER_IP_KEY);
+                IpAddress ip1 = IpAddress.valueOf(ipAddress1);
+                TunnelEndPoint tunnelAsSrcDst = IpTunnelEndPoint
+                        .ipTunnelPoint(ip1);
+                TunnelEndPoint tunnelAsDstSrc = IpTunnelEndPoint
+                        .ipTunnelPoint(ip1);
+                TunnelDescription tunnelAsSrc = new DefaultTunnelDescription(
+                                                                             tunnelAsSrcSrc,
+                                                                             tunnelAsSrcDst,
+                                                                             TunnelDescription.Type.VXLAN,
+                                                                             null);
+                TunnelDescription tunnelAsDst = new DefaultTunnelDescription(
+                                                                             tunnelAsDstDst,
+                                                                             tunnelAsDstSrc,
+                                                                             TunnelDescription.Type.VXLAN,
+                                                                             null);
+                config.createTunnel(tunnelAsSrc);
+                config.createTunnel(tunnelAsDst);
+            }
+        });
+    }
+
+    @Override
+    public void onServerVanished(Device device) {
+        Iterable<Device> devices = deviceService.getAvailableDevices();
+        DriverHandler handler = driverService.createHandler(device.id());
+        TunnelConfig config = handler.behaviour(TunnelConfig.class);
+        BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+        bridgeConfig.deleteBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
+        String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
+        IpAddress ip = IpAddress.valueOf(ipAddress);
+        TunnelEndPoint tunnelAsSrcSrc = IpTunnelEndPoint.ipTunnelPoint(ip);
+        TunnelEndPoint tunnelAsDstDst = IpTunnelEndPoint.ipTunnelPoint(ip);
+        devices.forEach(d -> {
+            if (!device.id().equals(d.id())) {
+                String ipAddress1 = d.annotations().value(CONTROLLER_IP_KEY);
+                IpAddress ip1 = IpAddress.valueOf(ipAddress1);
+                TunnelEndPoint tunnelAsSrcDst = IpTunnelEndPoint
+                        .ipTunnelPoint(ip1);
+                TunnelEndPoint tunnelAsDstSrc = IpTunnelEndPoint
+                        .ipTunnelPoint(ip1);
+                TunnelDescription tunnelAsSrc = new DefaultTunnelDescription(
+                                                                             tunnelAsSrcSrc,
+                                                                             tunnelAsSrcDst,
+                                                                             TunnelDescription.Type.VXLAN,
+                                                                             null);
+                TunnelDescription tunnelAsDst = new DefaultTunnelDescription(
+                                                                             tunnelAsDstDst,
+                                                                             tunnelAsDstSrc,
+                                                                             TunnelDescription.Type.VXLAN,
+                                                                             null);
+                config.removeTunnel(tunnelAsSrc);
+                config.removeTunnel(tunnelAsDst);
+            }
+        });
+    }
+
+    @Override
+    public void onOvsDetected(Device device) {
+        programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
+        programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
+    }
+
+    @Override
+    public void onOvsVanished(Device device) {
+        programMacDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
+        programPortDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
+    }
+
+    @Override
+    public void onHostDetected(Host host) {
+        String ifaceId = host.annotations().value(IFACEID);
+        VirtualPortId portId = VirtualPortId.portId(ifaceId);
+        VirtualPort port = virtualPortService.getPort(portId);
+        TenantNetwork network = tenantNetworkService.getNetwork(port
+                .networkId());
+        binding.put(host.id(), network.segmentationId());
+        DeviceId deviceId = host.location().deviceId();
+        List<Port> allPorts = deviceService.getPorts(deviceId);
+        PortNumber inPort = host.location().port();
+        Set<Port> localPorts = new HashSet<>();
+        allPorts.forEach(p -> {
+            if (!p.number().name().startsWith(PORT_HEAD)) {
+                localPorts.add(p);
+            }
+        });
+        programLocalBcastRules(deviceId, network.segmentationId(), inPort,
+                               allPorts, appId, Objective.Operation.ADD);
+        programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
+                        appId, Objective.Operation.ADD);
+        programTunnelFloodOut(deviceId, network.segmentationId(), inPort,
+                              localPorts, appId, Objective.Operation.ADD);
+        programTunnelOut(deviceId, network.segmentationId(), inPort,
+                         host.mac(), appId, Objective.Operation.ADD);
+        programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
+                       appId, Objective.Operation.ADD);
+        programTunnelIn(deviceId, network.segmentationId(), inPort, host.mac(),
+                        appId, Objective.Operation.ADD);
+    }
+
+    @Override
+    public void onHostVanished(Host host) {
+        SegmentationId segId = binding.remove(host.id());
+        DeviceId deviceId = host.location().deviceId();
+        List<Port> allPorts = deviceService.getPorts(deviceId);
+        PortNumber inPort = host.location().port();
+        Set<Port> localPorts = new HashSet<>();
+        allPorts.forEach(p -> {
+            if (!p.number().name().startsWith(PORT_HEAD)) {
+                localPorts.add(p);
+            }
+        });
+        programLocalBcastRules(deviceId, segId, inPort, allPorts, appId,
+                               Objective.Operation.REMOVE);
+        programLocalOut(deviceId, segId, inPort, host.mac(), appId,
+                        Objective.Operation.REMOVE);
+        programTunnelFloodOut(deviceId, segId, inPort, localPorts, appId,
+                              Objective.Operation.REMOVE);
+        programTunnelOut(deviceId, segId, inPort, host.mac(), appId,
+                         Objective.Operation.REMOVE);
+        programLocalIn(deviceId, segId, inPort, host.mac(), appId,
+                       Objective.Operation.REMOVE);
+        programTunnelIn(deviceId, segId, inPort, host.mac(), appId,
+                        Objective.Operation.REMOVE);
+    }
+
+    private class InnerDeviceListener implements DeviceListener {
+
+        @Override
+        public void event(DeviceEvent event) {
+            Device device = event.subject();
+            if (Device.Type.CONTROLLER == device.type()
+                    && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
+                backgroundService.execute(() -> {
+                    onServerDetected(device);
+                });
+            } else if (Device.Type.CONTROLLER == device.type()
+                    && DeviceEvent.Type.DEVICE_REMOVED == event.type()) {
+                backgroundService.execute(() -> {
+                    onServerVanished(device);
+                });
+            } else if (Device.Type.SWITCH == device.type()
+                    && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
+                backgroundService.execute(() -> {
+                    onOvsDetected(device);
+                });
+            } else if (Device.Type.SWITCH == device.type()
+                    && DeviceEvent.Type.DEVICE_REMOVED == event.type()) {
+                backgroundService.execute(() -> {
+                    onOvsVanished(device);
+                });
+            } else {
+                log.info("do nothing for this device type");
+            }
+        }
+
+    }
+
+    private class InnerHostListener implements HostListener {
+
+        @Override
+        public void event(HostEvent event) {
+            Host host = event.subject();
+            if (HostEvent.Type.HOST_ADDED == event.type()) {
+                backgroundService.execute(() -> {
+                    onHostDetected(host);
+                });
+            } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
+                backgroundService.execute(() -> {
+                    onHostVanished(host);
+                });
+            } else {
+                log.info("unknow host");
+            }
+        }
+
+    }
+
+    //Used to forward the flows to the local VM.
+    private void programLocalOut(DeviceId dpid, SegmentationId segmentationId,
+                                 PortNumber outPort, MacAddress sourceMac,
+                                 ApplicationId appid, Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthDst(sourceMac).matchEthType(ETH_TYPE_MAC).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment
+                .builder()
+                .add(Instructions.modTunnelId(Long.parseLong(segmentationId
+                             .toString()))).setOutput(outPort).build();
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+
+    }
+
+    //Used to forward the flows to the remote VM via VXLAN tunnel.
+    private void programTunnelOut(DeviceId dpid, SegmentationId segmentationId,
+                                  PortNumber outPort, MacAddress sourceMac,
+                                  ApplicationId appid, Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthDst(sourceMac).matchEthType(ETH_TYPE_MAC).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment
+                .builder()
+                .add(Instructions.modTunnelId(Long.parseLong(segmentationId
+                             .toString()))).setOutput(outPort).build();
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Used to forward multicast flows to remote VMs of the same tenant via VXLAN tunnel.
+    private void programTunnelFloodOut(DeviceId dpid,
+                                       SegmentationId segmentationId,
+                                       PortNumber ofPortOut,
+                                       Iterable<Port> localports,
+                                       ApplicationId appid,
+                                       Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector
+                .builder()
+                .matchInPort(ofPortOut)
+                .matchEthType(ETH_TYPE_MAC)
+                .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
+                             .toString()))).matchEthDst(MacAddress.BROADCAST)
+                .build();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+        for (Port outport : localports) {
+            treatment.setOutput(outport.number());
+        }
+
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment.build())
+                .withSelector(selector).fromApp(appId)
+
+                .makePermanent().withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Applies default flows to mac table.
+    private void programMacDefaultRules(DeviceId dpid, ApplicationId appid,
+                                        Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(ETH_TYPE_MAC).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().drop()
+                .build();
+
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Used to forward the flows to the local VMs with the same tenant.
+    private void programLocalBcastRules(DeviceId dpid,
+                                        SegmentationId segmentationId,
+                                        PortNumber inPort, List<Port> allports,
+                                        ApplicationId appid,
+                                        Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector
+                .builder()
+                .matchInPort(inPort)
+                .matchEthType(ETH_TYPE_MAC)
+                .matchEthDst(MacAddress.BROADCAST)
+                .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
+                             .toString()))).build();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+        for (Port outport : allports) {
+            if (inPort != outport.number()) {
+                treatment.setOutput(outport.number());
+            }
+        }
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment.build())
+                .withSelector(selector).fromApp(appId).makePermanent()
+                .withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Used to apply local entry flow.
+    private void programLocalIn(DeviceId dpid, SegmentationId segmentationId,
+                                PortNumber inPort, MacAddress srcMac,
+                                ApplicationId appid, Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchInPort(inPort).matchEthSrc(srcMac)
+                .matchEthType(ETH_TYPE_PORT).build();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+        treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId
+                .toString())));
+        treatment.transition(MAC_TABLE);
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment.build())
+                .withSelector(selector).fromApp(appId).makePermanent()
+                .withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Used to forward the flows from the egress tunnel to the VM.
+    private void programTunnelIn(DeviceId dpid, SegmentationId segmentationId,
+                                 PortNumber inPort, MacAddress sourceMac,
+                                 ApplicationId appid, Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector
+                .builder()
+                .matchInPort(inPort)
+                .matchEthType(ETH_TYPE_PORT)
+                .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
+                             .toString()))).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .transition(MAC_TABLE).build();
+
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+
+    //Applies the default flows to port table.
+    private void programPortDefaultRules(DeviceId dpid, ApplicationId appid,
+                                         Objective.Operation type) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(ETH_TYPE_PORT).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .transition(MAC_TABLE).build();
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(dpid, objective.add());
+        } else {
+            flowObjectiveService.forward(dpid, objective.remove());
+        }
+    }
+}
diff --git a/apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java b/apps/vtn/src/main/java/org/onosproject/vtn/impl/package-info.java
similarity index 95%
rename from apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java
rename to apps/vtn/src/main/java/org/onosproject/vtn/impl/package-info.java
index 488adc5..f18dbf8 100644
--- a/apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/impl/package-info.java
@@ -17,4 +17,4 @@
 /**
  * VTN application that applies configuration and flows to the device.
  */
-package org.onosproject.app.vtn;
+package org.onosproject.vtn.impl;
diff --git a/apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java b/apps/vtn/src/main/java/org/onosproject/vtn/package-info.java
similarity index 95%
copy from apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java
copy to apps/vtn/src/main/java/org/onosproject/vtn/package-info.java
index 488adc5..371466c 100644
--- a/apps/vtn/src/main/java/org/onosproject/app/vtn/package-info.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/package-info.java
@@ -17,4 +17,4 @@
 /**
  * VTN application that applies configuration and flows to the device.
  */
-package org.onosproject.app.vtn;
+package org.onosproject.vtn;
diff --git a/apps/vtnrsc/pom.xml b/apps/vtnrsc/pom.xml
index 774b182..dbfc410 100644
--- a/apps/vtnrsc/pom.xml
+++ b/apps/vtnrsc/pom.xml
@@ -17,7 +17,6 @@
 
 	<properties>
 		<onos.app.name>org.onosproject.vtnrsc</onos.app.name>
-		<web.context>/onos/vtn</web.context>
 	</properties>
 	<dependencies>
 		<dependency>
@@ -52,7 +51,6 @@
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
-                        <_wab>src/main/webapp/</_wab>
                         <Bundle-SymbolicName>
                             ${project.groupId}.${project.artifactId}
                         </Bundle-SymbolicName>
@@ -76,7 +74,6 @@
                             org.onlab.util.*,
                             org.jboss.netty.util.*
                         </Import-Package>
-                        <Web-ContextPath>${web.context}</Web-ContextPath>
                     </instructions>
                 </configuration>
             </plugin>