diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
index 64923bb..417a795 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
@@ -32,7 +32,7 @@
 /**
  * Implementation of the default l2 tunnel.
  */
-public class DefaultL2Tunnel {
+public class DefaultL2Tunnel implements L2Tunnel {
 
     /**
      * Mode of the pseudo wire.
@@ -132,6 +132,7 @@
      *
      * @return the pseudo wire mode
      */
+    @Override
     public L2Mode pwMode() {
         return pwMode;
     }
@@ -142,6 +143,7 @@
      *
      * @return the service delimitation vlan id
      */
+    @Override
     public VlanId sdTag() {
         return sdTag;
     }
@@ -151,6 +153,7 @@
      *
      * @return the pseudo wire tunnel id
      */
+    @Override
     public long tunnelId() {
         return tunnelId;
     }
@@ -160,6 +163,7 @@
      *
      * @return the mpls pw label
      */
+    @Override
     public MplsLabel pwLabel() {
         return pwLabel;
     }
@@ -169,6 +173,7 @@
      *
      * @param path The path to set
      */
+    @Override
     public void setPath(List<Link> path) {
         pathUsed = new ArrayList<>(path);
     }
@@ -178,6 +183,7 @@
      *
      * @param vlan the vlan to use.
      */
+    @Override
     public void setTransportVlan(VlanId vlan) {
         transportVlan = vlan;
     }
@@ -187,10 +193,12 @@
      *
      * @return pathUsed
      */
+    @Override
     public List<Link> pathUsed() {
         return pathUsed;
     }
 
+    @Override
     public VlanId transportVlan() {
         return transportVlan;
     }
@@ -201,6 +209,7 @@
      *
      * @return the mpls inter-co label
      */
+    @Override
     public MplsLabel interCoLabel() {
         return interCoLabel;
     }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
index b5206a3..7a47972 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
@@ -26,17 +26,17 @@
  * Helper class to carry the l2 tunnel
  * and its policy.
  */
-public class DefaultL2TunnelDescription {
+public class DefaultL2TunnelDescription implements L2TunnelDescription {
 
     /**
      * The l2 tunnel.
      */
-    private DefaultL2Tunnel l2Tunnel;
+    private L2Tunnel l2Tunnel;
 
     /**
      * The l2 tunnel policy.
      */
-    private DefaultL2TunnelPolicy l2TunnelPolicy;
+    private L2TunnelPolicy l2TunnelPolicy;
 
     /**
      * Creates a l2 tunnel description using the given info.
@@ -44,8 +44,8 @@
      * @param l2Tunnel the l2 tunnel
      * @param l2TunnelPolicy the l2 tunnel description
      */
-    public DefaultL2TunnelDescription(DefaultL2Tunnel l2Tunnel,
-                                      DefaultL2TunnelPolicy l2TunnelPolicy) {
+    public DefaultL2TunnelDescription(L2Tunnel l2Tunnel,
+                                      L2TunnelPolicy l2TunnelPolicy) {
         checkNotNull(l2Tunnel);
         checkNotNull(l2TunnelPolicy);
 
@@ -61,39 +61,23 @@
         this.l2TunnelPolicy = null;
     }
 
-    /**
-     * Returns the l2 tunnel.
-     *
-     * @return the l2 tunnel
-     */
-    public DefaultL2Tunnel l2Tunnel() {
+    @Override
+    public L2Tunnel l2Tunnel() {
         return l2Tunnel;
     }
 
-    /**
-     * Returns the l2 tunnel policy.
-     *
-     * @return the l2 tunnel policy.
-     */
-    public DefaultL2TunnelPolicy l2TunnelPolicy() {
+    @Override
+    public L2TunnelPolicy l2TunnelPolicy() {
         return l2TunnelPolicy;
     }
 
-    /**
-     * Sets the l2 tunnel.
-     *
-     * @param tunnel the l2 tunnel to set.
-     */
-    public void setL2Tunnel(DefaultL2Tunnel tunnel) {
+    @Override
+    public void setL2Tunnel(L2Tunnel tunnel) {
         l2Tunnel = tunnel;
     }
 
-    /**
-     * Sets the l2 policy.
-     *
-     * @param policy the policy to set.
-     */
-    public void setL2TunnelPolicy(DefaultL2TunnelPolicy policy) {
+    @Override
+    public void setL2TunnelPolicy(L2TunnelPolicy policy) {
         l2TunnelPolicy = policy;
     }
 
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
new file mode 100644
index 0000000..df02417
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
@@ -0,0 +1,1725 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.segmentrouting.pwaas;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.RandomUtils;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flowobjective.DefaultFilteringObjective;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
+import org.onosproject.net.flowobjective.DefaultObjectiveContext;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveContext;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.segmentrouting.SegmentRoutingManager;
+import org.onosproject.segmentrouting.SegmentRoutingService;
+import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
+import org.onosproject.segmentrouting.config.PwaasConfig;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.DistributedSet;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
+import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
+import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
+import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result.*;
+import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.FWD;
+import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.REV;
+
+/**
+ * Handles pwaas related events.
+ */
+public class DefaultL2TunnelHandler implements L2TunnelHandler {
+
+    private static final Logger log = LoggerFactory.getLogger(DefaultL2TunnelHandler.class);
+
+    private final SegmentRoutingManager srManager;
+    /**
+     * To store the next objectives related to the initiation.
+     */
+    private final ConsistentMap<String, NextObjective> l2InitiationNextObjStore;
+    /**
+     * To store the next objectives related to the termination.
+     */
+    private final ConsistentMap<String, NextObjective> l2TerminationNextObjStore;
+
+    /**
+     * To store policies.
+     */
+    private final ConsistentMap<String, L2TunnelPolicy> l2PolicyStore;
+
+    /**
+     * To store tunnels.
+     */
+    private final ConsistentMap<String, L2Tunnel> l2TunnelStore;
+
+    private final KryoNamespace.Builder l2TunnelKryo;
+
+    /**
+     * Contains transport vlans used for spine-leaf pseudowires.
+     */
+    private final DistributedSet<VlanId> vlanStore;
+
+    /**
+     * Used for determining transport vlans for leaf-spine.
+     */
+    private short transportVlanUpper = 4093, transportVlanLower = 3500;
+
+    private static final VlanId UNTAGGED_TRANSPORT_VLAN = VlanId.vlanId((short) 4094);
+
+    /**
+     * Create a l2 tunnel handler for the deploy and
+     * for the tear down of pseudo wires.
+     *
+     * @param segmentRoutingManager the segment routing manager
+     */
+    public DefaultL2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
+        srManager = segmentRoutingManager;
+        l2TunnelKryo = new KryoNamespace.Builder()
+                .register(KryoNamespaces.API)
+                .register(L2Tunnel.class,
+                          L2TunnelPolicy.class,
+                          DefaultL2Tunnel.class,
+                          DefaultL2TunnelPolicy.class,
+                          L2Mode.class,
+                          MplsLabel.class,
+                          VlanId.class,
+                          ConnectPoint.class);
+
+        l2InitiationNextObjStore = srManager.
+                storageService.
+                <String, NextObjective>consistentMapBuilder().
+                withName("onos-l2initiation-nextobj-store").
+                withSerializer(Serializer.using(l2TunnelKryo.build())).
+                build();
+
+        l2TerminationNextObjStore = srManager.storageService.
+                <String, NextObjective>consistentMapBuilder()
+                .withName("onos-l2termination-nextobj-store")
+                .withSerializer(Serializer.using(l2TunnelKryo.build()))
+                .build();
+
+        l2PolicyStore = srManager.storageService
+                .<String, L2TunnelPolicy>consistentMapBuilder()
+                .withName("onos-l2-policy-store")
+                .withSerializer(Serializer.using(l2TunnelKryo.build()))
+                .build();
+
+        l2TunnelStore = srManager.storageService
+                .<String, L2Tunnel>consistentMapBuilder()
+                .withName("onos-l2-tunnel-store")
+                .withSerializer(Serializer.using(l2TunnelKryo.build()))
+                .build();
+
+        vlanStore = srManager.storageService.<VlanId>setBuilder()
+                .withName("onos-transport-vlan-store")
+                .withSerializer(Serializer.using(
+                        new KryoNamespace.Builder()
+                                .register(KryoNamespaces.API)
+                                .build()))
+                .build()
+                .asDistributedSet();
+    }
+
+    /**
+     * Deploys any pre-existing pseudowires in the configuration.
+     * Used by manager only in initialization.
+     */
+    @Override
+    public void init() {
+
+        PwaasConfig config = srManager.cfgService.getConfig(srManager.appId(), PwaasConfig.class);
+        if (config == null) {
+            return;
+        }
+
+        log.info("Deploying existing pseudowires");
+
+        // gather pseudowires
+        Set<L2TunnelDescription> pwToAdd = config
+                .getPwIds()
+                .stream()
+                .map(config::getPwDescription)
+                .collect(Collectors.toSet());
+
+        // deploy pseudowires
+        deploy(pwToAdd);
+    }
+
+    /**
+     * Returns all L2 Policies.
+     *
+     * @return List of policies
+     */
+    @Override
+    public List<L2TunnelPolicy> getL2Policies() {
+
+        return new ArrayList<>(l2PolicyStore
+                .values()
+                .stream()
+                .map(Versioned::value)
+                .collect(Collectors.toList()));
+
+    }
+
+    /**
+     * Returns all L2 Tunnels.
+     *
+     * @return List of tunnels.
+     */
+    @Override
+    public List<L2Tunnel> getL2Tunnels() {
+
+        return new ArrayList<>(l2TunnelStore
+                .values()
+                .stream()
+                .map(Versioned::value)
+                .collect(Collectors.toList()));
+
+    }
+
+    @Override
+    public void processLinkDown(Link link) {
+
+        List<L2Tunnel> tunnels = getL2Tunnels();
+        List<L2TunnelPolicy> policies = getL2Policies();
+
+        // determine affected pseudowires and update them at once
+        Set<L2TunnelDescription> pwToUpdate = tunnels
+                .stream()
+                .filter(tun -> tun.pathUsed().contains(link))
+                .map(l2Tunnel -> {
+                        L2TunnelPolicy policy = null;
+                        for (L2TunnelPolicy l2Policy : policies) {
+                            if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
+                                policy = l2Policy;
+                                break;
+                            }
+                        }
+
+                        return new DefaultL2TunnelDescription(l2Tunnel, policy);
+                })
+                .collect(Collectors.toSet());
+
+
+        log.info("Pseudowires affected by link failure : {}, rerouting them...", pwToUpdate);
+
+        // update all pseudowires
+        pwToUpdate.forEach(tun -> updatePw(tun, tun));
+    }
+
+    @Override
+    public void processPwaasConfigAdded(NetworkConfigEvent event) {
+        checkArgument(event.config().isPresent(),
+                "Config is not presented in PwaasConfigAdded event {}", event);
+
+        log.info("Network event : Pseudowire configuration added!");
+        PwaasConfig config = (PwaasConfig) event.config().get();
+
+        // gather pseudowires
+        Set<L2TunnelDescription> pwToAdd = config
+                .getPwIds()
+                .stream()
+                .map(config::getPwDescription)
+                .collect(Collectors.toSet());
+
+        // deploy pseudowires
+        deploy(pwToAdd);
+    }
+
+    /**
+     * Returns the new vlan id for an ingress point of a
+     * pseudowire. For double tagged, it is the outer,
+     * For single tagged it is the single tag, and for
+     * inner it is None.
+     *
+     * @param ingressOuter vlanid of ingress outer
+     * @param ingressInner vlanid of ingress inner
+     * @param egressOuter  vlanid of egress outer
+     * @param egressInner  vlanid of egress inner
+     * @return returns the vlan id which will be installed at vlan table 1.
+     */
+    private VlanId determineEgressVlan(VlanId ingressOuter, VlanId ingressInner,
+                                      VlanId egressOuter, VlanId egressInner) {
+
+        // validity of vlan combinations was checked at verifyPseudowire
+        if (!(ingressOuter.equals(VlanId.NONE))) {
+            return egressOuter;
+        } else if (!(ingressInner.equals(VlanId.NONE))) {
+            return egressInner;
+        } else {
+            return VlanId.vlanId("None");
+        }
+    }
+
+    /**
+     * Determines vlan used for transporting the pw traffic.
+     *
+     * Leaf-Leaf traffic is transferred untagged, thus we choose the UNTAGGED_TRANSPORT_VLAN
+     * and also make sure to add the popVlan instruction.
+     * For spine-leaf pws we choose the highest vlan value available from a certain range.
+     *
+     * @param spinePw if the pw is leaf-spine.
+     * @return The vlan id chossen to transport this pseudowire. If vlan is UNTAGGED_TRANSPORT_VLAN
+     *         then the pw is transported untagged.
+     */
+    private VlanId determineTransportVlan(boolean spinePw) {
+
+        if (!spinePw) {
+
+            log.info("Untagged transport with internal vlan {} for pseudowire!", UNTAGGED_TRANSPORT_VLAN);
+            return UNTAGGED_TRANSPORT_VLAN;
+        } else {
+            for (short i = transportVlanUpper; i > transportVlanLower; i--) {
+
+                VlanId vlanToUse = VlanId.vlanId((short) i);
+                if (!vlanStore.contains(vlanToUse)) {
+
+                    vlanStore.add(vlanToUse);
+                    log.info("Transport vlan {} for pseudowire!", vlanToUse);
+                    return vlanToUse;
+                }
+            }
+
+            log.info("No available transport vlan found, pseudowire traffic will be carried untagged " +
+                             "with internal vlan {}!", UNTAGGED_TRANSPORT_VLAN);
+            return UNTAGGED_TRANSPORT_VLAN;
+        }
+    }
+
+    /**
+     * Adds a single pseudowire from leaf to a leaf.
+     * This method can be called from cli commands
+     * without configuration updates, thus it does not check for mastership
+     * of the ingress pseudowire device.
+     *
+     * @param pw The pseudowire
+     * @param spinePw True if pseudowire is from leaf to spine
+     * @return result of pseudowire deployment
+     */
+    private Result deployPseudowire(L2TunnelDescription pw, boolean spinePw) {
+
+        Result result;
+        long l2TunnelId;
+
+        l2TunnelId = pw.l2Tunnel().tunnelId();
+
+        // The tunnel id cannot be 0.
+        if (l2TunnelId == 0) {
+            log.warn("Tunnel id id must be > 0");
+            return Result.ADDITION_ERROR;
+        }
+
+        // get path here, need to use the same for fwd and rev direction
+        List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
+                                  pw.l2TunnelPolicy().cP2());
+        if (path == null) {
+            log.info("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
+            return WRONG_PARAMETERS;
+        }
+
+        Link fwdNextHop;
+        Link revNextHop;
+        if (!spinePw) {
+            if (path.size() != 2) {
+                log.info("Deploying process : Path between two leafs should have size of 2, for pseudowire {}",
+                         l2TunnelId);
+                return INTERNAL_ERROR;
+            }
+
+            fwdNextHop = path.get(0);
+            revNextHop = reverseLink(path.get(1));
+        } else {
+            if (path.size() != 1) {
+                log.info("Deploying process : Path between leaf spine should equal to 1, for pseudowire {}",
+                         l2TunnelId);
+                return INTERNAL_ERROR;
+            }
+
+            fwdNextHop = path.get(0);
+            revNextHop = reverseLink(path.get(0));
+        }
+
+        pw.l2Tunnel().setPath(path);
+        pw.l2Tunnel().setTransportVlan(determineTransportVlan(spinePw));
+
+        // next hops for next objectives
+
+        log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
+
+        // We establish the tunnel.
+        // result.nextId will be used in fwd
+        result = deployPseudoWireInit(pw.l2Tunnel(),
+                                      pw.l2TunnelPolicy().cP1(),
+                                      pw.l2TunnelPolicy().cP2(),
+                                      FWD,
+                                      fwdNextHop,
+                                      spinePw);
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
+            return Result.ADDITION_ERROR;
+        }
+
+        VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
+                                                pw.l2TunnelPolicy().cP1InnerTag(),
+                                                pw.l2TunnelPolicy().cP2OuterTag(),
+                                                pw.l2TunnelPolicy().cP2InnerTag());
+
+        // We create the policy.
+        result = deployPolicy(l2TunnelId,
+                              pw.l2TunnelPolicy().cP1(),
+                              pw.l2TunnelPolicy().cP1InnerTag(),
+                              pw.l2TunnelPolicy().cP1OuterTag(),
+                              egressVlan,
+                              result.nextId);
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying pseudowire policy for CP1");
+            return Result.ADDITION_ERROR;
+        }
+
+        // We terminate the tunnel
+        result = deployPseudoWireTerm(pw.l2Tunnel(),
+                                       pw.l2TunnelPolicy().cP2(),
+                                       VlanId.NONE,
+                                       FWD,
+                                      spinePw);
+
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying pseudowire termination for CP1");
+            return Result.ADDITION_ERROR;
+
+        }
+
+        log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
+
+        // We establish the reverse tunnel.
+        result = deployPseudoWireInit(pw.l2Tunnel(),
+                                       pw.l2TunnelPolicy().cP2(),
+                                       pw.l2TunnelPolicy().cP1(),
+                                       REV,
+                                       revNextHop,
+                                       spinePw);
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying pseudowire initiation for CP2");
+            return Result.ADDITION_ERROR;
+        }
+
+        egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
+                                          pw.l2TunnelPolicy().cP2InnerTag(),
+                                          pw.l2TunnelPolicy().cP1OuterTag(),
+                                          pw.l2TunnelPolicy().cP1InnerTag());
+        result = deployPolicy(l2TunnelId,
+                               pw.l2TunnelPolicy().cP2(),
+                               pw.l2TunnelPolicy().cP2InnerTag(),
+                               pw.l2TunnelPolicy().cP2OuterTag(),
+                               egressVlan,
+                               result.nextId);
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying policy for CP2");
+            return Result.ADDITION_ERROR;
+        }
+
+        result = deployPseudoWireTerm(pw.l2Tunnel(),
+                                       pw.l2TunnelPolicy().cP1(),
+                                       VlanId.NONE,
+                                       REV,
+                                      spinePw);
+
+        if (result != SUCCESS) {
+            log.info("Deploying process : Error in deploying pseudowire termination for CP2");
+            return Result.ADDITION_ERROR;
+        }
+
+        log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
+
+        // Populate stores
+        l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
+        l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
+
+        return Result.SUCCESS;
+    }
+
+    /**
+     * To deploy a number of pseudo wires.
+     * <p>
+     * Called ONLY when configuration changes, thus the check
+     * for the mastership of the device.
+     * <p>
+     * Only the master of CP1 will deploy this pseudowire.
+     *
+     * @param pwToAdd the set of pseudo wires to add
+     */
+    private void deploy(Set<L2TunnelDescription> pwToAdd) {
+
+        Result result;
+
+        for (L2TunnelDescription currentL2Tunnel : pwToAdd) {
+            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
+            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
+            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
+
+            // only the master of CP1 will program this pseudowire
+            if (!srManager.isMasterOf(cp1)) {
+                log.debug("Not the master of {}. Ignore pseudo wire deployment id={}", cp1, tunnelId);
+                continue;
+            }
+
+            try {
+                // differentiate between leaf-leaf pseudowires and leaf-spine
+                // and pass the appropriate flag in them.
+                if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
+                    !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
+                    log.warn("Can not deploy pseudowire from spine to spine!");
+                    result = Result.INTERNAL_ERROR;
+                } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
+                     srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
+                    log.info("Deploying a leaf-leaf pseudowire {}", tunnelId);
+                    result = deployPseudowire(currentL2Tunnel, false);
+                } else {
+                    log.info("Deploying a leaf-spine pseudowire {}", tunnelId);
+                    result = deployPseudowire(currentL2Tunnel, true);
+                }
+            } catch (DeviceConfigNotFoundException e) {
+                log.error("Exception caught when deploying pseudowire", e.toString());
+                result = Result.INTERNAL_ERROR;
+            }
+
+            switch (result) {
+                case INTERNAL_ERROR:
+                    log.warn("Could not deploy pseudowire {}, internal error!", tunnelId);
+                    break;
+                case WRONG_PARAMETERS:
+                    log.warn("Could not deploy pseudowire {}, wrong parameters!", tunnelId);
+                    break;
+                case ADDITION_ERROR:
+                    log.warn("Could not deploy pseudowire {}, error in populating rules!", tunnelId);
+                    break;
+                default:
+                    log.info("Pseudowire with {} succesfully deployed!", tunnelId);
+                    break;
+            }
+        }
+    }
+
+
+    @Override
+    public void processPwaasConfigUpdated(NetworkConfigEvent event) {
+        checkArgument(event.config().isPresent(),
+                "Config is not presented in PwaasConfigUpdated event {}", event);
+        checkArgument(event.prevConfig().isPresent(),
+                "PrevConfig is not presented in PwaasConfigUpdated event {}", event);
+
+        log.info("Pseudowire configuration updated.");
+
+        // We retrieve the old pseudo wires.
+        PwaasConfig prevConfig = (PwaasConfig) event.prevConfig().get();
+        Set<Long> prevPws = prevConfig.getPwIds();
+
+        // We retrieve the new pseudo wires.
+        PwaasConfig config = (PwaasConfig) event.config().get();
+        Set<Long> newPws = config.getPwIds();
+
+        // We compute the pseudo wires to update.
+        Set<Long> updPws = newPws.stream()
+                .filter(tunnelId -> prevPws.contains(tunnelId)
+                        && !config.getPwDescription(tunnelId).equals(prevConfig.getPwDescription(tunnelId)))
+                .collect(Collectors.toSet());
+
+        // The pseudo wires to remove.
+        Set<Long> rmvPWs = prevPws.stream()
+                .filter(tunnelId -> !newPws.contains(tunnelId)).collect(Collectors.toSet());
+
+        Set<L2TunnelDescription> pwToRemove = rmvPWs.stream()
+                .map(prevConfig::getPwDescription)
+                .collect(Collectors.toSet());
+        tearDown(pwToRemove);
+
+        // The pseudo wires to add.
+        Set<Long> addedPWs = newPws.stream()
+                .filter(tunnelId -> !prevPws.contains(tunnelId))
+                .collect(Collectors.toSet());
+        Set<L2TunnelDescription> pwToAdd = addedPWs.stream()
+                .map(config::getPwDescription)
+                .collect(Collectors.toSet());
+        deploy(pwToAdd);
+
+
+        // The pseudo wires to update.
+        updPws.forEach(tunnelId -> updatePw(prevConfig.getPwDescription(tunnelId),
+                                            config.getPwDescription(tunnelId)));
+
+        log.info("Pseudowires removed : {}, Pseudowires updated : {}, Pseudowires added : {}", rmvPWs,
+                 updPws, addedPWs);
+    }
+
+    /**
+     * Helper function to update a pw.
+     * <p>
+     * Called upon configuration changes that update existing pseudowires and
+     * when links fail. Checking of mastership for CP1 is mandatory because it is
+     * called in multiple instances for both cases.
+     * <p>
+     * Meant to call asynchronously for various events, thus this call can not block and need
+     * to perform asynchronous operations.
+     * <p>
+     * For this reason error checking is omitted.
+     *
+     * @param oldPw the pseudo wire to remove
+     * @param newPw the pseudo wire to add
+     */
+    private void updatePw(L2TunnelDescription oldPw,
+                         L2TunnelDescription newPw) {
+        ConnectPoint oldCp1 = oldPw.l2TunnelPolicy().cP1();
+        long tunnelId = oldPw.l2Tunnel().tunnelId();
+
+        // only the master of CP1 will update this pseudowire
+        if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) {
+            log.debug("Not the master of {}. Ignore pseudo wire update id={}", oldCp1, tunnelId);
+            return;
+        }
+        // only determine if the new pseudowire is leaf-spine, because
+        // removal process is the same for both leaf-leaf and leaf-spine pws
+        boolean newPwSpine;
+        try {
+            newPwSpine = !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP1().deviceId()) ||
+                    !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP2().deviceId());
+        } catch (DeviceConfigNotFoundException e) {
+            // if exception is caught treat the new pw as leaf-leaf
+            newPwSpine = false;
+        }
+
+        // copy the variable here because we need to use it in lambda thus it needs to be final
+        boolean finalNewPwSpine = newPwSpine;
+
+        log.info("Updating pseudowire {}", oldPw.l2Tunnel().tunnelId());
+
+        // The async tasks to orchestrate the next and forwarding update
+        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> fwdPwFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> revPwFuture = new CompletableFuture<>();
+
+        // first delete all information from our stores, we can not do it asynchronously
+        l2PolicyStore.remove(Long.toString(tunnelId));
+
+        // grab the old l2 tunnel from the store, since it carries information which is not exposed
+        // to the user configuration and set it to oldPw.
+        oldPw.setL2Tunnel(l2TunnelStore.get(Long.toString(tunnelId)).value());
+        VlanId transportVlan = l2TunnelStore.get(Long.toString(tunnelId)).value().transportVlan();
+        l2TunnelStore.remove(Long.toString(tunnelId));
+
+        // remove the reserved transport vlan, if one is used
+        if (!transportVlan.equals(UNTAGGED_TRANSPORT_VLAN)) {
+            vlanStore.remove(transportVlan);
+        }
+
+        // First we remove both policy.
+        log.debug("Start deleting fwd policy for {}", tunnelId);
+        VlanId egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP1OuterTag(),
+                                                 oldPw.l2TunnelPolicy().cP1InnerTag(),
+                                                 oldPw.l2TunnelPolicy().cP2OuterTag(),
+                                                 oldPw.l2TunnelPolicy().cP2InnerTag());
+        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP1(),
+                      oldPw.l2TunnelPolicy().cP1InnerTag(),
+                      oldPw.l2TunnelPolicy().cP1OuterTag(),
+                      egressVlan,
+                      fwdInitNextFuture,
+                      FWD);
+
+        log.debug("Update process : Start deleting rev policy for {}", tunnelId);
+        egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP2OuterTag(),
+                                          oldPw.l2TunnelPolicy().cP2InnerTag(),
+                                          oldPw.l2TunnelPolicy().cP1OuterTag(),
+                                          oldPw.l2TunnelPolicy().cP1InnerTag());
+        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP2(),
+                      oldPw.l2TunnelPolicy().cP2InnerTag(),
+                      oldPw.l2TunnelPolicy().cP2OuterTag(),
+                      egressVlan, revInitNextFuture,
+                      REV);
+
+        // Finally we remove both the tunnels.
+        fwdInitNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                log.debug("Update process : Fwd policy removed. " +
+                                  "Now remove fwd {} for {}", INITIATION, tunnelId);
+                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP1(), fwdTermNextFuture, FWD);
+            }
+        });
+        revInitNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                log.debug("Update process : Rev policy removed. " +
+                                  "Now remove rev {} for {}", INITIATION, tunnelId);
+                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP2(), revTermNextFuture, REV);
+            }
+        });
+        fwdTermNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                log.debug("Update process : Fwd {} removed. " +
+                                  "Now remove fwd {} for {}", INITIATION, TERMINATION, tunnelId);
+                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP2(),  fwdPwFuture, FWD);
+            }
+        });
+        revTermNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                log.debug("Update process : Rev {} removed. " +
+                                  "Now remove rev {} for {}", INITIATION, TERMINATION, tunnelId);
+                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP1(), revPwFuture, REV);
+            }
+        });
+
+        // get path here, need to use the same for fwd and rev direction
+        List<Link> path = getPath(newPw.l2TunnelPolicy().cP1(),
+                                   newPw.l2TunnelPolicy().cP2());
+        if (path == null) {
+            log.error("Update process : " +
+                             "No path between the connection points for pseudowire {}", newPw.l2Tunnel().tunnelId());
+            return;
+        }
+
+        Link fwdNextHop, revNextHop;
+        if (!finalNewPwSpine) {
+            if (path.size() != 2) {
+                log.error("Update process : Error, path between two leafs should have size of 2, for pseudowire {}",
+                         newPw.l2Tunnel().tunnelId());
+                return;
+            }
+            fwdNextHop = path.get(0);
+            revNextHop = reverseLink(path.get(1));
+        } else {
+            if (path.size() != 1) {
+                log.error("Update process : Error, path between leaf spine should equal to 1, for pseudowire {}",
+                         newPw.l2Tunnel().tunnelId());
+                return;
+            }
+            fwdNextHop = path.get(0);
+            revNextHop = reverseLink(path.get(0));
+        }
+
+        // set new path and transport vlan.
+        newPw.l2Tunnel().setPath(path);
+        newPw.l2Tunnel().setTransportVlan(determineTransportVlan(newPwSpine));
+
+        // At the end we install the updated PW.
+        fwdPwFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+
+                // Upgrade stores and book keeping information, need to move this here
+                // cause this call is asynchronous.
+                l2PolicyStore.put(Long.toString(tunnelId), newPw.l2TunnelPolicy());
+                l2TunnelStore.put(Long.toString(tunnelId), newPw.l2Tunnel());
+
+                log.debug("Update process : Deploying new fwd pw for {}", tunnelId);
+                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP1(),
+                                                           newPw.l2TunnelPolicy().cP2(), FWD,
+                                                           fwdNextHop, finalNewPwSpine);
+                if (lamdaResult != SUCCESS) {
+                    return;
+                }
+
+                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP1OuterTag(),
+                                                          newPw.l2TunnelPolicy().cP1InnerTag(),
+                                                           newPw.l2TunnelPolicy().cP2OuterTag(),
+                                                          newPw.l2TunnelPolicy().cP2InnerTag());
+
+                lamdaResult = deployPolicy(tunnelId, newPw.l2TunnelPolicy().cP1(),
+                                            newPw.l2TunnelPolicy().cP1InnerTag(),
+                                           newPw.l2TunnelPolicy().cP1OuterTag(),
+                                            egressVlanId, lamdaResult.nextId);
+                if (lamdaResult != SUCCESS) {
+                    return;
+                }
+                deployPseudoWireTerm(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP2(),
+                                      VlanId.NONE, FWD, finalNewPwSpine);
+
+            }
+        });
+        revPwFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+
+                log.debug("Update process : Deploying new rev pw for {}", tunnelId);
+                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(),
+                                                           newPw.l2TunnelPolicy().cP2(),
+                                                           newPw.l2TunnelPolicy().cP1(),
+                                                           REV,
+                                                           revNextHop, finalNewPwSpine);
+                if (lamdaResult != SUCCESS) {
+                    return;
+                }
+
+                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP2OuterTag(),
+                                                           newPw.l2TunnelPolicy().cP2InnerTag(),
+                                                           newPw.l2TunnelPolicy().cP1OuterTag(),
+                                                           newPw.l2TunnelPolicy().cP1InnerTag());
+                lamdaResult = deployPolicy(tunnelId,
+                                            newPw.l2TunnelPolicy().cP2(),
+                                            newPw.l2TunnelPolicy().cP2InnerTag(),
+                                            newPw.l2TunnelPolicy().cP2OuterTag(),
+                                            egressVlanId,
+                                            lamdaResult.nextId);
+                if (lamdaResult != SUCCESS) {
+                    return;
+                }
+                deployPseudoWireTerm(newPw.l2Tunnel(),
+                                      newPw.l2TunnelPolicy().cP1(),
+                                      VlanId.NONE,
+                                      REV, finalNewPwSpine);
+            }
+        });
+    }
+
+    @Override
+    public void processPwaasConfigRemoved(NetworkConfigEvent event) {
+        checkArgument(event.prevConfig().isPresent(),
+                "PrevConfig is not presented in PwaasConfigRemoved event {}", event);
+
+        log.info("Network event : Pseudowire configuration removed!");
+        PwaasConfig config = (PwaasConfig) event.prevConfig().get();
+
+        Set<L2TunnelDescription> pwToRemove = config
+                .getPwIds()
+                .stream()
+                .map(config::getPwDescription)
+                .collect(Collectors.toSet());
+
+        // We teardown all the pseudo wire deployed
+        tearDown(pwToRemove);
+    }
+
+    /**
+     * Helper function for removing a single pseudowire.
+     * <p>
+     * No mastership of CP1 is checked, because it can be called from
+     * the CLI for removal of pseudowires.
+     *
+     * @param l2TunnelId the id of the pseudowire to tear down
+     * @return Returns SUCCESS if no error is obeserved or an appropriate
+     * error on a failure
+     */
+    private Result tearDownPseudowire(long l2TunnelId) {
+
+        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
+
+        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
+        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
+
+        if (l2TunnelId == 0) {
+            log.warn("Removal process : Tunnel id cannot be 0");
+            return Result.WRONG_PARAMETERS;
+        }
+
+        // check existence of tunnels/policy in the store, if one is missing abort!
+        Versioned<L2Tunnel> l2TunnelVersioned = l2TunnelStore.get(Long.toString(l2TunnelId));
+        Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = l2PolicyStore.get(Long.toString(l2TunnelId));
+        if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
+            log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
+            return Result.REMOVAL_ERROR;
+        }
+
+        L2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(),
+                                                                               l2TunnelPolicyVersioned.value());
+
+        // remove the tunnels and the policies from the store
+        l2PolicyStore.remove(Long.toString(l2TunnelId));
+        l2TunnelStore.remove(Long.toString(l2TunnelId));
+
+        // remove the reserved transport vlan
+        if (!pwToRemove.l2Tunnel().transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
+            vlanStore.remove(pwToRemove.l2Tunnel().transportVlan());
+        }
+
+        log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);
+
+        VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(),
+                                                 pwToRemove.l2TunnelPolicy().cP1InnerTag(),
+                                                 pwToRemove.l2TunnelPolicy().cP2OuterTag(),
+                                                 pwToRemove.l2TunnelPolicy().cP2InnerTag());
+        deletePolicy(l2TunnelId,
+                      pwToRemove.l2TunnelPolicy().cP1(),
+                      pwToRemove.l2TunnelPolicy().cP1InnerTag(),
+                      pwToRemove.l2TunnelPolicy().cP1OuterTag(),
+                      egressVlan,
+                      fwdInitNextFuture,
+                      FWD);
+
+        fwdInitNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                // Finally we will tear down the pseudo wire.
+                tearDownPseudoWireInit(l2TunnelId,
+                                        pwToRemove.l2TunnelPolicy().cP1(),
+                                        fwdTermNextFuture,
+                                        FWD);
+            }
+        });
+
+        fwdTermNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
+                                        pwToRemove.l2TunnelPolicy().cP2(),
+                                        null,
+                                        FWD);
+            }
+        });
+
+        log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);
+
+        egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(),
+                                          pwToRemove.l2TunnelPolicy().cP2InnerTag(),
+                                          pwToRemove.l2TunnelPolicy().cP1OuterTag(),
+                                          pwToRemove.l2TunnelPolicy().cP1InnerTag());
+
+        // We do the same operations on the reverse side.
+        deletePolicy(l2TunnelId,
+                      pwToRemove.l2TunnelPolicy().cP2(),
+                      pwToRemove.l2TunnelPolicy().cP2InnerTag(),
+                      pwToRemove.l2TunnelPolicy().cP2OuterTag(),
+                      egressVlan,
+                      revInitNextFuture,
+                      REV);
+
+        revInitNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                tearDownPseudoWireInit(l2TunnelId,
+                                        pwToRemove.l2TunnelPolicy().cP2(),
+                                        revTermNextFuture,
+                                        REV);
+            }
+        });
+
+        revTermNextFuture.thenAcceptAsync(status -> {
+            if (status == null) {
+                tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
+                                        pwToRemove.l2TunnelPolicy().cP1(),
+                                        null,
+                                        REV);
+            }
+        });
+
+        return Result.SUCCESS;
+    }
+
+    @Override
+    public void tearDown(Set<L2TunnelDescription> pwToRemove) {
+
+        Result result;
+
+        // We remove all the pw in the configuration file.
+        for (L2TunnelDescription currentL2Tunnel : pwToRemove) {
+            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
+            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
+            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
+
+            // only the master of CP1 will program this pseudowire
+            if (!srManager.isMasterOf(cp1)) {
+                log.debug("Not the master of {}. Ignore pseudo wire removal id={}", cp1, tunnelId);
+                continue;
+            }
+
+            // no need to differentiate here between leaf-leaf and leaf-spine, because
+            // the only change is in the groups, which we do not remove either way
+            log.info("Removing pseudowire {}", tunnelId);
+
+            result = tearDownPseudowire(tunnelId);
+            switch (result) {
+                case WRONG_PARAMETERS:
+                    log.warn("Error in supplied parameters for the pseudowire removal with tunnel id {}!",
+                            tunnelId);
+                    break;
+                case REMOVAL_ERROR:
+                    log.warn("Error in pseudowire removal with tunnel id {}!", tunnelId);
+                    break;
+                default:
+                    log.warn("Pseudowire with tunnel id {} was removed successfully", tunnelId);
+            }
+        }
+    }
+
+    /**
+     * Handles the policy establishment which consists in
+     * create the filtering and forwarding objectives related
+     * to the initiation and termination.
+     *
+     * @param tunnelId     the tunnel id
+     * @param ingress      the ingress point
+     * @param ingressInner the ingress inner tag
+     * @param ingressOuter the ingress outer tag
+     * @param nextId       the next objective id
+     * @param egressVlan   Vlan-id to set, depends on ingress vlan
+     *                     combinations. For example, if pw is double tagged
+     *                     then this is the value of the outer vlan, if single
+     *                     tagged then it is the new value of the single tag.
+     *                     Should be None for untagged traffic.
+     * @return the result of the operation
+     */
+    private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
+                                VlanId ingressOuter, VlanId egressVlan, int nextId) {
+
+        List<Objective> objectives = Lists.newArrayList();
+        // We create the forwarding objective for supporting
+        // the l2 tunnel.
+        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
+        // We create and add objective context.
+        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
+                                                                log.debug("FwdObj for tunnel {} populated", tunnelId),
+                                                               (objective, error) ->
+                                                                log.warn("Failed to populate fwdrObj " +
+                                                                                 "for tunnel {}", tunnelId, error));
+        objectives.add(fwdBuilder.add(context));
+
+        // We create the filtering objective to define the
+        // permit traffic in the switch
+        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
+
+        // We add the metadata.
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+                .builder()
+                .setTunnelId(tunnelId)
+                .setVlanId(egressVlan);
+        filtBuilder.withMeta(treatment.build());
+
+        // We create and add objective context.
+        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
+                                              (objective, error) -> log.warn("Failed to populate filterObj for " +
+                                                                                     "tunnel {}", tunnelId, error));
+        objectives.add(filtBuilder.add(context));
+
+        for (Objective objective : objectives) {
+            if (objective instanceof ForwardingObjective) {
+                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
+                log.debug("Creating new FwdObj for initiation NextObj with id={} for tunnel {}", nextId, tunnelId);
+            } else {
+                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
+                log.debug("Creating new FiltObj for tunnel {}", tunnelId);
+            }
+        }
+        return SUCCESS;
+    }
+
+    /**
+     * Handles the tunnel establishment which consists in
+     * create the next objectives related to the initiation.
+     *
+     * @param l2Tunnel  the tunnel to deploy
+     * @param ingress   the ingress connect point
+     * @param egress    the egress connect point
+     * @param direction the direction of the pw
+     * @param spinePw if the pseudowire involves a spine switch
+     * @return the result of the operation
+     */
+    private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress,
+                                        ConnectPoint egress, Direction direction, Link nextHop, boolean spinePw) {
+
+        if (nextHop == null) {
+            log.warn("No path between ingress and egress cps for tunnel {}", l2Tunnel.tunnelId());
+            return WRONG_PARAMETERS;
+        }
+
+        // We create the next objective without the metadata
+        // context and id. We check if it already exists in the
+        // store. If not we store as it is in the store.
+        NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION,
+                                                                         nextHop.src(),
+                                                                         nextHop.dst(),
+                                                                         l2Tunnel,
+                                                                         egress.deviceId(),
+                                                                         spinePw);
+
+        if (nextObjectiveBuilder == null) {
+            return INTERNAL_ERROR;
+        }
+        // We set the metadata. We will use this metadata
+        // to inform the driver we are doing a l2 tunnel.
+        TrafficSelector metadata = DefaultTrafficSelector
+                .builder()
+                .matchTunnelId(l2Tunnel.tunnelId())
+                .build();
+        nextObjectiveBuilder.withMeta(metadata);
+        int nextId = srManager.flowObjectiveService.allocateNextId();
+        if (nextId < 0) {
+            log.warn("Not able to allocate a next id for initiation");
+            return INTERNAL_ERROR;
+        }
+        nextObjectiveBuilder.withId(nextId);
+        String key = generateKey(l2Tunnel.tunnelId(), direction);
+        l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
+        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
+                                                                 log.debug("Initiation l2 tunnel rule " +
+                                                                                   "for {} populated",
+                                                                           l2Tunnel.tunnelId()),
+                                                               (objective, error) ->
+                                                                       log.warn("Failed to populate Initiation " +
+                                                                                        "l2 tunnel rule for {}: {}",
+                                                                                l2Tunnel.tunnelId(), error));
+        NextObjective nextObjective = nextObjectiveBuilder.add(context);
+        srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
+        log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}",
+                  l2Tunnel.tunnelId(), nextObjective.id());
+        Result result = SUCCESS;
+        result.nextId = nextObjective.id();
+        return result;
+    }
+
+    /**
+     * Handles the tunnel termination, which consists in the creation
+     * of a forwarding objective and a next objective.
+     *
+     * @param l2Tunnel   the tunnel to terminate
+     * @param egress     the egress point
+     * @param egressVlan the expected vlan at egress
+     * @param direction  the direction
+     * @param spinePw if the pseudowire involves a spine switch
+     * @return the result of the operation
+     */
+    private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress,
+                                        VlanId egressVlan, Direction direction, boolean spinePw) {
+
+        // We create the group relative to the termination.
+        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
+                                                                         l2Tunnel, egress.deviceId(),
+                                                                         spinePw);
+        if (nextObjectiveBuilder == null) {
+            return INTERNAL_ERROR;
+        }
+        TrafficSelector metadata = DefaultTrafficSelector
+                .builder()
+                .matchVlanId(egressVlan)
+                .build();
+        nextObjectiveBuilder.withMeta(metadata);
+        int nextId = srManager.flowObjectiveService.allocateNextId();
+        if (nextId < 0) {
+            log.warn("Not able to allocate a next id for initiation");
+            return INTERNAL_ERROR;
+        }
+        nextObjectiveBuilder.withId(nextId);
+        String key = generateKey(l2Tunnel.tunnelId(), direction);
+        l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
+        ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("Termination l2 tunnel rule " +
+                                                                                        "for {} populated",
+                                                                                        l2Tunnel.tunnelId()),
+                                                               (objective, error) -> log.warn("Failed to populate " +
+                                                                                              "termination l2 tunnel " +
+                                                                                              "rule for {}: {}",
+                                                                                              l2Tunnel.tunnelId(),
+                                                                                              error));
+        NextObjective nextObjective = nextObjectiveBuilder.add(context);
+        srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
+        log.debug("Termination next objective for {} not found. Creating new NextObj with id={}",
+                  l2Tunnel.tunnelId(), nextObjective.id());
+
+        // We create the flow relative to the termination.
+        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(),
+                                                                        egress.port(), nextObjective.id());
+        context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
+                                                                       l2Tunnel.tunnelId()),
+                                              (objective, error) -> log.warn("Failed to populate fwdrObj" +
+                                                                             " for tunnel termination {}",
+                                                                             l2Tunnel.tunnelId(), error));
+        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
+        log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
+                  nextId, l2Tunnel.tunnelId());
+
+        if (spinePw) {
+
+            // determine the input port at the
+            PortNumber inPort;
+
+            if (egress.deviceId().
+                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
+                    inPort = l2Tunnel.pathUsed().get(0).dst().port();
+            } else {
+                    inPort = l2Tunnel.pathUsed().get(0).src().port();
+            }
+
+            MacAddress dstMac;
+            try {
+                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
+            } catch (Exception e) {
+                log.info("Device not found in configuration, no programming of MAC address");
+                dstMac = null;
+            }
+
+            log.info("Populating filtering objective for pseudowire transport" +
+                             " with vlan = {}, port = {}, mac = {}",
+                     l2Tunnel.transportVlan(),
+                     inPort,
+                     dstMac);
+            FilteringObjective.Builder filteringObjectiveBuilder =
+                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
+            context = new DefaultObjectiveContext(( objective ) ->
+                                                          log.debug("Special filtObj for  " + "for {} populated",
+                                                                    l2Tunnel.tunnelId()),
+                                                  ( objective, error ) ->
+                                                          log.warn("Failed to populate " +
+                                                                           "special filtObj " +
+                                                                           "rule for {}: {}",
+                                                                                   l2Tunnel.tunnelId(), error));
+            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+            filteringObjectiveBuilder.withMeta(treatment.build());
+            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.add(context));
+            log.debug("Creating new special FiltObj for termination point with tunnel {} for port {}",
+                      l2Tunnel.tunnelId(),
+                      inPort);
+        }
+
+        return SUCCESS;
+    }
+
+
+    /**
+     * Creates the filtering objective according to a given port and vlanid.
+     *
+     * @param inPort   the in port
+     * @param vlanId the inner vlan tag
+     * @return the filtering objective
+     */
+    private FilteringObjective.Builder createNormalPipelineFiltObjective(PortNumber inPort,
+                                                                         VlanId vlanId,
+                                                                         MacAddress dstMac) {
+
+        log.info("Creating filtering objective for pseudowire transport with vlan={}, port={}, mac={}",
+                 vlanId,
+                 inPort,
+                 dstMac);
+        FilteringObjective.Builder fwdBuilder = DefaultFilteringObjective
+                .builder()
+                .withKey(Criteria.matchInPort(inPort))
+                .addCondition(Criteria.matchVlanId(vlanId))
+                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
+                .permit()
+                .fromApp(srManager.appId());
+
+        if (dstMac != null) {
+            fwdBuilder.addCondition(Criteria.matchEthDst(dstMac));
+        }
+
+        return fwdBuilder;
+    }
+
+    /**
+     * Creates the filtering objective according to a given policy.
+     *
+     * @param inPort   the in port
+     * @param innerTag the inner vlan tag
+     * @param outerTag the outer vlan tag
+     * @return the filtering objective
+     */
+    private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {
+
+        log.info("Creating filtering objective for vlans {} / {}", outerTag, innerTag);
+        return DefaultFilteringObjective
+                .builder()
+                .withKey(Criteria.matchInPort(inPort))
+                .addCondition(Criteria.matchInnerVlanId(innerTag))
+                .addCondition(Criteria.matchVlanId(outerTag))
+                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
+                .permit()
+                .fromApp(srManager.appId());
+    }
+
+    /**
+     * Creates the forwarding objective for the termination.
+     *
+     * @param pwLabel    the pseudo wire label
+     * @param tunnelId   the tunnel id
+     * @param egressPort the egress port
+     * @param nextId     the next step
+     * @return the forwarding objective to support the termination
+     */
+    private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
+                                                               PortNumber egressPort, int nextId) {
+
+        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
+        // The flow has to match on the pw label and bos
+        trafficSelector.matchEthType(Ethernet.MPLS_UNICAST);
+        trafficSelector.matchMplsLabel(pwLabel);
+        trafficSelector.matchMplsBos(true);
+        // The flow has to decrement ttl, restore ttl in
+        // pop mpls, set tunnel id and port.
+        trafficTreatment.decMplsTtl();
+        trafficTreatment.copyTtlIn();
+        trafficTreatment.popMpls();
+        trafficTreatment.setTunnelId(tunnelId);
+        trafficTreatment.setOutput(egressPort);
+
+        return DefaultForwardingObjective
+                .builder()
+                .fromApp(srManager.appId())
+                .makePermanent()
+                .nextStep(nextId)
+                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
+                .withSelector(trafficSelector.build())
+                .withTreatment(trafficTreatment.build())
+                .withFlag(VERSATILE);
+    }
+
+    /**
+     * Creates the forwarding objective for the initiation.
+     *
+     * @param tunnelId the tunnel id
+     * @param inPort   the input port
+     * @param nextId   the next step
+     * @return the forwarding objective to support the initiation.
+     */
+    private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {
+
+        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
+
+        // The flow has to match on the mpls logical
+        // port and the tunnel id.
+        trafficSelector.matchTunnelId(tunnelId);
+        trafficSelector.matchInPort(inPort);
+
+        return DefaultForwardingObjective
+                .builder()
+                .fromApp(srManager.appId())
+                .makePermanent()
+                .nextStep(nextId)
+                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
+                .withSelector(trafficSelector.build())
+                .withFlag(VERSATILE);
+
+    }
+
+    /**
+     * Creates the next objective according to a given
+     * pipeline. We don't set the next id and we don't
+     * create the final meta to check if we are re-using
+     * the same next objective for different tunnels.
+     *
+     * @param pipeline the pipeline to support
+     * @param srcCp    the source port
+     * @param dstCp    the destination port
+     * @param l2Tunnel the tunnel to support
+     * @param egressId the egress device id
+     * @param spinePw if the pw involves a spine switch
+     * @return the next objective to support the pipeline
+     */
+    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
+                                                      ConnectPoint dstCp,  L2Tunnel l2Tunnel,
+                                                      DeviceId egressId, boolean spinePw) {
+        NextObjective.Builder nextObjBuilder;
+        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+        if (pipeline == INITIATION) {
+            nextObjBuilder = DefaultNextObjective
+                    .builder()
+                    .withType(NextObjective.Type.SIMPLE)
+                    .fromApp(srManager.appId());
+            // The pw label is the bottom of stack. It has to
+            // be different -1.
+            if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
+                log.warn("Pw label not configured");
+                return null;
+            }
+            treatmentBuilder.pushMpls();
+            treatmentBuilder.setMpls(l2Tunnel.pwLabel());
+            treatmentBuilder.setMplsBos(true);
+            treatmentBuilder.copyTtlOut();
+
+            // If the inter-co label is present we have to set the label.
+            if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
+                treatmentBuilder.pushMpls();
+                treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
+                treatmentBuilder.setMplsBos(false);
+                treatmentBuilder.copyTtlOut();
+            }
+
+            // if pw is leaf-to-leaf we need to
+            // add the routing label also
+            if (!spinePw) {
+                // We retrieve the sr label from the config
+                // specific for pseudowire traffic
+                // using the egress leaf device id.
+                MplsLabel srLabel;
+                try {
+                    srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
+
+                } catch (DeviceConfigNotFoundException e) {
+                    log.warn("Sr label for pw traffic not configured");
+                    return null;
+                }
+
+                treatmentBuilder.pushMpls();
+                treatmentBuilder.setMpls(srLabel);
+                treatmentBuilder.setMplsBos(false);
+                treatmentBuilder.copyTtlOut();
+            }
+
+            // We have to rewrite the src and dst mac address.
+            MacAddress ingressMac;
+            try {
+                ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
+            } catch (DeviceConfigNotFoundException e) {
+                log.warn("Was not able to find the ingress mac");
+                return null;
+            }
+            treatmentBuilder.setEthSrc(ingressMac);
+            MacAddress neighborMac;
+            try {
+                neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
+            } catch (DeviceConfigNotFoundException e) {
+                log.warn("Was not able to find the neighbor mac");
+                return null;
+            }
+            treatmentBuilder.setEthDst(neighborMac);
+
+            // if not a leaf-spine pw we need to POP the vlan at the output
+            // since we carry this traffic untagged.
+            if (!spinePw) {
+                treatmentBuilder.popVlan();
+            }
+        } else {
+            // We create the next objective which
+            // will be a simple l2 group.
+            nextObjBuilder = DefaultNextObjective
+                    .builder()
+                    .withType(NextObjective.Type.SIMPLE)
+                    .fromApp(srManager.appId());
+        }
+
+        // set the appropriate transport vlan
+        treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
+        treatmentBuilder.setOutput(srcCp.port());
+        nextObjBuilder.addTreatment(treatmentBuilder.build());
+        return nextObjBuilder;
+    }
+
+    /**
+     * Reverses a link.
+     *
+     * @param link link to be reversed
+     * @return the reversed link
+     */
+    private Link reverseLink(Link link) {
+
+        DefaultLink.Builder linkBuilder = DefaultLink.builder();
+
+        linkBuilder.src(link.dst());
+        linkBuilder.dst(link.src());
+        linkBuilder.type(link.type());
+        linkBuilder.providerId(link.providerId());
+
+        return linkBuilder.build();
+    }
+
+    /**
+     * Returns the path betwwen two connect points.
+     *
+     * @param srcCp source connect point
+     * @param dstCp destination connect point
+     * @return the path
+     */
+    private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {
+        /* TODO We retrieve a set of paths in case of a link failure, what happens
+         * if the TopologyService gets the link notification AFTER us and has not updated the paths?
+         *
+         * TODO This has the potential to act on old topology.
+         * Maybe we should make SRManager be a listener on topology events instead raw link events.
+         */
+        Set<Path> paths = srManager.topologyService.getPaths(
+                srManager.topologyService.currentTopology(),
+                srcCp.deviceId(), dstCp.deviceId());
+
+        log.debug("Paths obtained from topology service {}", paths);
+
+        // We randomly pick a path.
+        if (paths.isEmpty()) {
+            return null;
+        }
+        int size = paths.size();
+        int index = RandomUtils.nextInt(0, size);
+
+        List<Link> result = Iterables.get(paths, index).links();
+        log.debug("Randomly picked a path {}", result);
+
+        return result;
+    }
+
+    /**
+     * Deletes a given policy using the parameter supplied.
+     *
+     * @param tunnelId     the tunnel id
+     * @param ingress      the ingress point
+     * @param ingressInner the ingress inner vlan id
+     * @param ingressOuter the ingress outer vlan id
+     * @param future       to perform the async operation
+     * @param direction    the direction: forward or reverse
+     */
+    private void deletePolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner, VlanId ingressOuter,
+                              VlanId egressVlan, CompletableFuture<ObjectiveError> future, Direction direction) {
+
+        String key = generateKey(tunnelId, direction);
+        if (!l2InitiationNextObjStore.containsKey(key)) {
+            log.warn("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
+            if (future != null) {
+                future.complete(null);
+            }
+            return;
+        }
+        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
+        int nextId = nextObjective.id();
+        List<Objective> objectives = Lists.newArrayList();
+        // We create the forwarding objective.
+        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
+        ObjectiveContext context = new ObjectiveContext() {
+            @Override
+            public void onSuccess(Objective objective) {
+                log.debug("Previous fwdObj for policy {} removed", tunnelId);
+                if (future != null) {
+                    future.complete(null);
+                }
+            }
+
+            @Override
+            public void onError(Objective objective, ObjectiveError error) {
+                log.warn("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
+                if (future != null) {
+                    future.complete(error);
+                }
+            }
+        };
+        objectives.add(fwdBuilder.remove(context));
+        // We create the filtering objective to define the
+        // permit traffic in the switch
+        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+                .builder()
+                .setTunnelId(tunnelId)
+                .setVlanId(egressVlan);
+        filtBuilder.withMeta(treatment.build());
+        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for policy {} revoked", tunnelId),
+                                              (objective, error) ->
+                                                      log.warn("Failed to revoke filterObj for policy {}",
+                                                               tunnelId, error));
+        objectives.add(filtBuilder.remove(context));
+
+        for (Objective objective : objectives) {
+            if (objective instanceof ForwardingObjective) {
+                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
+            } else {
+                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
+            }
+        }
+    }
+
+    /**
+     * Deletes the pseudo wire initiation.
+     *
+     * @param l2TunnelId the tunnel id
+     * @param ingress    the ingress connect point
+     * @param future     to perform an async operation
+     * @param direction  the direction: reverse of forward
+     */
+    private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
+                                        CompletableFuture<ObjectiveError> future, Direction direction) {
+
+        String key = generateKey(l2TunnelId, direction);
+        if (!l2InitiationNextObjStore.containsKey(key)) {
+            log.info("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
+            if (future != null) {
+                future.complete(null);
+            }
+            return;
+        }
+        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
+
+        // un-comment in case you want to delete groups used by the pw
+        // however, this will break the update of pseudowires cause the L2 interface group can
+        // not be deleted (it is referenced by other groups)
+        /*
+        ObjectiveContext context = new ObjectiveContext() {
+            @Override
+            public void onSuccess(Objective objective) {
+                log.debug("Previous {} next for {} removed", INITIATION, key);
+                if (future != null) {
+                    future.complete(null);
+                }
+            }
+
+            @Override
+            public void onError(Objective objective, ObjectiveError error) {
+                log.warn("Failed to remove previous {} next for {}: {}", INITIATION, key, error);
+                if (future != null) {
+                    future.complete(error);
+                }
+            }
+        };
+        srManager.flowObjectiveService.next(ingress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
+        */
+
+        future.complete(null);
+        l2InitiationNextObjStore.remove(key);
+    }
+
+    /**
+     * Deletes the pseudo wire termination.
+     *
+     * @param l2Tunnel  the tunnel
+     * @param egress    the egress connect point
+     * @param future    the async task
+     * @param direction the direction of the tunnel
+     */
+    private void tearDownPseudoWireTerm(L2Tunnel l2Tunnel,
+                                        ConnectPoint egress,
+                                        CompletableFuture<ObjectiveError> future,
+                                        Direction direction) {
+
+        String key = generateKey(l2Tunnel.tunnelId(), direction);
+        if (!l2TerminationNextObjStore.containsKey(key)) {
+            log.info("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
+            if (future != null) {
+                future.complete(null);
+            }
+            return;
+        }
+        NextObjective nextObjective = l2TerminationNextObjStore.get(key).value();
+        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(),
+                                                                        l2Tunnel.tunnelId(),
+                                                                        egress.port(),
+                                                                        nextObjective.id());
+        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
+                                                                       log.debug("FwdObj for {} {}, " +
+                                                                                         "direction {} removed",
+                                                                                        TERMINATION,
+                                                                                        l2Tunnel.tunnelId(),
+                                                                                        direction),
+                                                               (objective, error) ->
+                                                                       log.warn("Failed to remove fwdObj " +
+                                                                                        "for {} {}" +
+                                                                                        ", direction {}",
+                                                                                TERMINATION,
+                                                                                l2Tunnel.tunnelId(),
+                                                                                error,
+                                                                                direction));
+        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.remove(context));
+
+        // un-comment in case you want to delete groups used by the pw
+        // however, this will break the update of pseudowires cause the L2 interface group can
+        // not be deleted (it is referenced by other groups)
+        /*
+        context = new ObjectiveContext() {
+            @Override
+            public void onSuccess(Objective objective) {
+                log.debug("Previous {} next for {} removed", TERMINATION, key);
+                if (future != null) {
+                    future.complete(null);
+                }
+            }
+
+            @Override
+            public void onError(Objective objective, ObjectiveError error) {
+                log.warn("Failed to remove previous {} next for {}: {}", TERMINATION, key, error);
+                if (future != null) {
+                    future.complete(error);
+                }
+            }
+        };
+        srManager.flowObjectiveService.next(egress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
+        */
+
+        // delete the extra filtering objective for terminating
+        // spine-spine pws
+        if (!l2Tunnel.transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
+
+            // determine the input port at the
+            PortNumber inPort;
+
+            if (egress.deviceId().
+                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
+                inPort = l2Tunnel.pathUsed().get(0).dst().port();
+            } else {
+                inPort = l2Tunnel.pathUsed().get(0).src().port();
+            }
+
+            MacAddress dstMac;
+            try {
+                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
+            } catch (Exception e) {
+                log.info("Device not found in configuration, no programming of MAC address");
+                dstMac = null;
+            }
+
+            log.info("Removing filtering objective for pseudowire transport" +
+                             " with vlan = {}, port = {}, mac = {}",
+                     l2Tunnel.transportVlan(),
+                     inPort,
+                     dstMac);
+            FilteringObjective.Builder filteringObjectiveBuilder =
+                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
+            context = new DefaultObjectiveContext(( objective ) ->
+                                                          log.debug("Special filtObj for  " + "for {} removed",
+                                                                    l2Tunnel.tunnelId()), ( objective, error ) ->
+                    log.warn("Failed to populate " + "special filtObj " +
+                                     "rule for {}: {}", l2Tunnel.tunnelId(), error));
+            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+            filteringObjectiveBuilder.withMeta(treatment.build());
+            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.remove(context));
+            log.debug("Removing special FiltObj for termination point with tunnel {} for port {}",
+                      l2Tunnel.tunnelId(),
+                      inPort);
+        }
+
+        l2TerminationNextObjStore.remove(key);
+        future.complete(null);
+    }
+
+    /**
+     * Utilities to generate pw key.
+     *
+     * @param tunnelId  the tunnel id
+     * @param direction the direction of the pw
+     * @return the key of the store
+     */
+    private String generateKey(long tunnelId, Direction direction) {
+        return String.format("%s-%s", tunnelId, direction);
+    }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
index ac52f3e..4738744 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
@@ -27,7 +27,7 @@
 /**
  * Implementation of the default l2 tunnel policy.
  */
-public class DefaultL2TunnelPolicy {
+public class DefaultL2TunnelPolicy implements L2TunnelPolicy {
 
     /**
      * Id of the tunnel associated to this policy.
@@ -97,65 +97,37 @@
         this.cP2OuterTag = policy.cP2OuterTag;
     }
 
-    /**
-     * Returns the first connect point of the policy.
-     *
-     * @return first connect point
-     */
+    @Override
     public ConnectPoint cP1() {
         return cP1;
     }
 
-    /**
-     * Returns the second connect point of the policy.
-     *
-     * @return second connect point
-     */
+    @Override
     public ConnectPoint cP2() {
         return cP2;
     }
 
-    /**
-     * Returns the cP1 inner vlan tag of the policy.
-     *
-     * @return cP1 inner vlan tag
-     */
+    @Override
     public VlanId cP1InnerTag() {
         return cP1InnerTag;
     }
 
-    /**
-     * Returns the cP1 outer vlan tag of the policy.
-     *
-     * @return cP1 outer vlan tag
-     */
+    @Override
     public VlanId cP1OuterTag() {
         return cP1OuterTag;
     }
 
-    /**
-     * Returns the cP2 inner vlan tag of the policy.
-     *
-     * @return cP2 inner vlan tag
-     */
+    @Override
     public VlanId cP2InnerTag() {
         return cP2InnerTag;
     }
 
-    /**
-     * Returns the cP2 outer vlan tag of the policy.
-     *
-     * @return cP2 outer vlan tag
-     */
+    @Override
     public VlanId cP2OuterTag() {
         return cP2OuterTag;
     }
 
-    /**
-     * Returns the tunnel ID of the policy.
-     *
-     * @return Tunnel ID
-     */
+    @Override
     public long tunnelId() {
         return this.tunnelId;
     }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
new file mode 100644
index 0000000..3e98480
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.segmentrouting.pwaas;
+
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.Link;
+
+import java.util.List;
+
+public interface L2Tunnel {
+
+    /**
+     * Return the mode of the l2 tunnel.
+     *
+     * @return The pw mode.
+     */
+    L2Mode pwMode();
+
+    /**
+     * Returns the service delimiting tag.
+     *
+     * @return the sd tag
+     */
+    VlanId sdTag();
+
+    /**
+     * Returns the id of the tunnel.
+     *
+     * @return the tunnel id
+     */
+    long tunnelId();
+
+    /**
+     * Return the label of the pseudowire.
+     *
+     * @return the pw label.
+     */
+    MplsLabel pwLabel();
+
+    /**
+     * Returns the path used by the pseudowire.
+     *
+     * @return The path that is used
+     */
+    List<Link> pathUsed();
+
+    /**
+     * Returns the transport vlan used by the pseudowire.
+     *
+     * @return The transport vlan
+     */
+    VlanId transportVlan();
+
+    /**
+     * Returns the inter-co label used by the pseudowire.
+     *
+     * @return The inter CO label.
+     */
+    MplsLabel interCoLabel();
+
+    /**
+     * Sets the path that this pw uses.
+     *
+     * @param path The apth to use
+     */
+    void setPath(List<Link> path);
+
+    /**
+     * Set the transport vlan that this pw will use.
+     *
+     * @param vlan The vlan to use.
+     */
+    void setTransportVlan(VlanId vlan);
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
new file mode 100644
index 0000000..7be187a
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.segmentrouting.pwaas;
+
+public interface L2TunnelDescription {
+
+    /**
+     * Returns the l2 tunnel.
+     *
+     * @return the l2 tunnel
+     */
+    L2Tunnel l2Tunnel();
+
+    /**
+     * Returns the l2 tunnel policy.
+     *
+     * @return the l2 tunnel policy.
+     */
+    L2TunnelPolicy l2TunnelPolicy();
+
+    /**
+     * Sets the l2 tunnel.
+     *
+     * @param tunnel the l2 tunnel to set.
+     */
+    void setL2Tunnel(L2Tunnel tunnel);
+
+    /**
+     * Sets the l2 policy.
+     *
+     * @param policy the policy to set.
+     */
+    void setL2TunnelPolicy(L2TunnelPolicy policy);
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
index 133de0c..3a89a21 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
@@ -16,209 +16,28 @@
 
 package org.onosproject.segmentrouting.pwaas;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.PortNumber;
 import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.PwaasConfig;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.DistributedSet;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.Versioned;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result.*;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.FWD;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.REV;
-
-/**
- * Handles pwaas related events.
- */
-public class L2TunnelHandler {
-
-    private static final Logger log = LoggerFactory.getLogger(L2TunnelHandler.class);
-
-    private final SegmentRoutingManager srManager;
-    /**
-     * To store the next objectives related to the initiation.
-     */
-    private final ConsistentMap<String, NextObjective> l2InitiationNextObjStore;
-    /**
-     * To store the next objectives related to the termination.
-     */
-    private final ConsistentMap<String, NextObjective> l2TerminationNextObjStore;
+public interface L2TunnelHandler {
+    void init();
 
     /**
-     * To store policies.
-     */
-    private final ConsistentMap<String, DefaultL2TunnelPolicy> l2PolicyStore;
-
-    /**
-     * To store tunnels.
-     */
-    private final ConsistentMap<String, DefaultL2Tunnel> l2TunnelStore;
-
-    private final KryoNamespace.Builder l2TunnelKryo;
-
-    /**
-     * Contains transport vlans used for spine-leaf pseudowires.
-     */
-    private final DistributedSet<VlanId> vlanStore;
-
-    /**
-     * Used for determining transport vlans for leaf-spine.
-     */
-    private short transportVlanUpper = 4093, transportVlanLower = 3500;
-
-    private static final VlanId UNTAGGED_TRANSPORT_VLAN = VlanId.vlanId((short) 4094);
-
-    /**
-     * Create a l2 tunnel handler for the deploy and
-     * for the tear down of pseudo wires.
+     * Returns a copy of the l2 policies that exist in the store.
      *
-     * @param segmentRoutingManager the segment routing manager
+     * @return The l2 policies
      */
-    public L2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
-        srManager = segmentRoutingManager;
-        l2TunnelKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(DefaultL2Tunnel.class,
-                          DefaultL2TunnelPolicy.class,
-                          L2Mode.class,
-                          MplsLabel.class,
-                          VlanId.class,
-                          ConnectPoint.class);
-
-        l2InitiationNextObjStore = srManager.
-                storageService.
-                <String, NextObjective>consistentMapBuilder().
-                withName("onos-l2initiation-nextobj-store").
-                withSerializer(Serializer.using(l2TunnelKryo.build())).
-                build();
-
-        l2TerminationNextObjStore = srManager.storageService.
-                <String, NextObjective>consistentMapBuilder()
-                .withName("onos-l2termination-nextobj-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        l2PolicyStore = srManager.storageService
-                .<String, DefaultL2TunnelPolicy>consistentMapBuilder()
-                .withName("onos-l2-policy-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        l2TunnelStore = srManager.storageService
-                .<String, DefaultL2Tunnel>consistentMapBuilder()
-                .withName("onos-l2-tunnel-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        vlanStore = srManager.storageService.<VlanId>setBuilder()
-                .withName("onos-transport-vlan-store")
-                .withSerializer(Serializer.using(
-                        new KryoNamespace.Builder()
-                                .register(KryoNamespaces.API)
-                                .build()))
-                .build()
-                .asDistributedSet();
-    }
+    List<L2TunnelPolicy> getL2Policies();
 
     /**
-     * Deploys any pre-existing pseudowires in the configuration.
-     * Used by manager only in initialization.
-     */
-    public void init() {
-
-        PwaasConfig config = srManager.cfgService.getConfig(srManager.appId(), PwaasConfig.class);
-        if (config == null) {
-            return;
-        }
-
-        log.info("Deploying existing pseudowires");
-
-        // gather pseudowires
-        Set<DefaultL2TunnelDescription> pwToAdd = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // deploy pseudowires
-        deploy(pwToAdd);
-    }
-
-    /**
-     * Returns all L2 Policies.
+     * Returns a copy of the l2 tunnels that exist in the store.
      *
-     * @return List of policies
+     * @return The l2 tunnels.
      */
-    public List<DefaultL2TunnelPolicy> getL2Policies() {
-
-        return l2PolicyStore
-                .values()
-                .stream()
-                .map(Versioned::value)
-                .map(DefaultL2TunnelPolicy::new)
-                .collect(Collectors.toList());
-
-    }
-
-    /**
-     * Returns all L2 Tunnels.
-     *
-     * @return List of tunnels.
-     */
-    public List<DefaultL2Tunnel> getL2Tunnels() {
-
-        return l2TunnelStore
-                .values()
-                .stream()
-                .map(Versioned::value)
-                .map(DefaultL2Tunnel::new)
-                .collect(Collectors.toList());
-
-    }
+    List<L2Tunnel> getL2Tunnels();
 
     /**
      * Processes a link removal. Finds affected pseudowires and rewires them.
@@ -226,1526 +45,44 @@
      * traffic in the spine.
      * @param link The link that failed
      */
-    public void processLinkDown(Link link) {
-
-        List<DefaultL2Tunnel> tunnels = getL2Tunnels();
-        List<DefaultL2TunnelPolicy> policies = getL2Policies();
-
-        // determine affected pseudowires and update them at once
-        Set<DefaultL2TunnelDescription> pwToUpdate = tunnels
-                .stream()
-                .filter(tun -> tun.pathUsed().contains(link))
-                .map(l2Tunnel -> {
-                        DefaultL2TunnelPolicy policy = null;
-                        for (DefaultL2TunnelPolicy l2Policy : policies) {
-                            if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
-                                policy = l2Policy;
-                                break;
-                            }
-                        }
-
-                        return new DefaultL2TunnelDescription(l2Tunnel, policy);
-                })
-                .collect(Collectors.toSet());
-
-
-        log.info("Pseudowires affected by link failure : {}, rerouting them...", pwToUpdate);
-
-        // update all pseudowires
-        pwToUpdate.forEach(tun -> updatePw(tun, tun));
-    }
+    void processLinkDown(Link link);
 
     /**
      * Processes Pwaas Config added event.
      *
      * @param event network config add event
      */
-    public void processPwaasConfigAdded(NetworkConfigEvent event) {
-        checkArgument(event.config().isPresent(),
-                "Config is not presented in PwaasConfigAdded event {}", event);
-
-        log.info("Network event : Pseudowire configuration added!");
-        PwaasConfig config = (PwaasConfig) event.config().get();
-
-        // gather pseudowires
-        Set<DefaultL2TunnelDescription> pwToAdd = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // deploy pseudowires
-        deploy(pwToAdd);
-    }
-
-    /**
-     * Returns the new vlan id for an ingress point of a
-     * pseudowire. For double tagged, it is the outer,
-     * For single tagged it is the single tag, and for
-     * inner it is None.
-     *
-     * @param ingressOuter vlanid of ingress outer
-     * @param ingressInner vlanid of ingress inner
-     * @param egressOuter  vlanid of egress outer
-     * @param egressInner  vlanid of egress inner
-     * @return returns the vlan id which will be installed at vlan table 1.
-     */
-    private VlanId determineEgressVlan(VlanId ingressOuter, VlanId ingressInner,
-                                      VlanId egressOuter, VlanId egressInner) {
-
-        // validity of vlan combinations was checked at verifyPseudowire
-        if (!(ingressOuter.equals(VlanId.NONE))) {
-            return egressOuter;
-        } else if (!(ingressInner.equals(VlanId.NONE))) {
-            return egressInner;
-        } else {
-            return VlanId.vlanId("None");
-        }
-    }
-
-    /**
-     * Determines vlan used for transporting the pw traffic.
-     *
-     * Leaf-Leaf traffic is transferred untagged, thus we choose the UNTAGGED_TRANSPORT_VLAN
-     * and also make sure to add the popVlan instruction.
-     * For spine-leaf pws we choose the highest vlan value available from a certain range.
-     *
-     * @param spinePw if the pw is leaf-spine.
-     * @return The vlan id chossen to transport this pseudowire. If vlan is UNTAGGED_TRANSPORT_VLAN
-     *         then the pw is transported untagged.
-     */
-    private VlanId determineTransportVlan(boolean spinePw) {
-
-        if (!spinePw) {
-
-            log.info("Untagged transport with internal vlan {} for pseudowire!", UNTAGGED_TRANSPORT_VLAN);
-            return UNTAGGED_TRANSPORT_VLAN;
-        } else {
-            for (short i = transportVlanUpper; i > transportVlanLower; i--) {
-
-                VlanId vlanToUse = VlanId.vlanId((short) i);
-                if (!vlanStore.contains(vlanToUse)) {
-
-                    vlanStore.add(vlanToUse);
-                    log.info("Transport vlan {} for pseudowire!", vlanToUse);
-                    return vlanToUse;
-                }
-            }
-
-            log.info("No available transport vlan found, pseudowire traffic will be carried untagged " +
-                             "with internal vlan {}!", UNTAGGED_TRANSPORT_VLAN);
-            return UNTAGGED_TRANSPORT_VLAN;
-        }
-    }
-
-    /**
-     * Adds a single pseudowire from leaf to a leaf.
-     * This method can be called from cli commands
-     * without configuration updates, thus it does not check for mastership
-     * of the ingress pseudowire device.
-     *
-     * @param pw The pseudowire
-     * @param spinePw True if pseudowire is from leaf to spine
-     * @return result of pseudowire deployment
-     */
-    private Result deployPseudowire(DefaultL2TunnelDescription pw, boolean spinePw) {
-
-        Result result;
-        long l2TunnelId;
-
-        l2TunnelId = pw.l2Tunnel().tunnelId();
-
-        // The tunnel id cannot be 0.
-        if (l2TunnelId == 0) {
-            log.warn("Tunnel id id must be > 0");
-            return Result.ADDITION_ERROR;
-        }
-
-        // get path here, need to use the same for fwd and rev direction
-        List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
-                                  pw.l2TunnelPolicy().cP2());
-        if (path == null) {
-            log.info("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
-            return WRONG_PARAMETERS;
-        }
-
-        Link fwdNextHop;
-        Link revNextHop;
-        if (!spinePw) {
-            if (path.size() != 2) {
-                log.info("Deploying process : Path between two leafs should have size of 2, for pseudowire {}",
-                         l2TunnelId);
-                return INTERNAL_ERROR;
-            }
-
-            fwdNextHop = path.get(0);
-            revNextHop = reverseLink(path.get(1));
-        } else {
-            if (path.size() != 1) {
-                log.info("Deploying process : Path between leaf spine should equal to 1, for pseudowire {}",
-                         l2TunnelId);
-                return INTERNAL_ERROR;
-            }
-
-            fwdNextHop = path.get(0);
-            revNextHop = reverseLink(path.get(0));
-        }
-
-        pw.l2Tunnel().setPath(path);
-        pw.l2Tunnel().setTransportVlan(determineTransportVlan(spinePw));
-
-        // next hops for next objectives
-
-        log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
-
-        // We establish the tunnel.
-        // result.nextId will be used in fwd
-        result = deployPseudoWireInit(pw.l2Tunnel(),
-                                      pw.l2TunnelPolicy().cP1(),
-                                      pw.l2TunnelPolicy().cP2(),
-                                      FWD,
-                                      fwdNextHop,
-                                      spinePw);
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
-            return Result.ADDITION_ERROR;
-        }
-
-        VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
-                                                pw.l2TunnelPolicy().cP1InnerTag(),
-                                                pw.l2TunnelPolicy().cP2OuterTag(),
-                                                pw.l2TunnelPolicy().cP2InnerTag());
-
-        // We create the policy.
-        result = deployPolicy(l2TunnelId,
-                              pw.l2TunnelPolicy().cP1(),
-                              pw.l2TunnelPolicy().cP1InnerTag(),
-                              pw.l2TunnelPolicy().cP1OuterTag(),
-                              egressVlan,
-                              result.nextId);
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying pseudowire policy for CP1");
-            return Result.ADDITION_ERROR;
-        }
-
-        // We terminate the tunnel
-        result = deployPseudoWireTerm(pw.l2Tunnel(),
-                                       pw.l2TunnelPolicy().cP2(),
-                                       VlanId.NONE,
-                                       FWD,
-                                      spinePw);
-
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying pseudowire termination for CP1");
-            return Result.ADDITION_ERROR;
-
-        }
-
-        log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
-
-        // We establish the reverse tunnel.
-        result = deployPseudoWireInit(pw.l2Tunnel(),
-                                       pw.l2TunnelPolicy().cP2(),
-                                       pw.l2TunnelPolicy().cP1(),
-                                       REV,
-                                       revNextHop,
-                                       spinePw);
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying pseudowire initiation for CP2");
-            return Result.ADDITION_ERROR;
-        }
-
-        egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
-                                          pw.l2TunnelPolicy().cP2InnerTag(),
-                                          pw.l2TunnelPolicy().cP1OuterTag(),
-                                          pw.l2TunnelPolicy().cP1InnerTag());
-        result = deployPolicy(l2TunnelId,
-                               pw.l2TunnelPolicy().cP2(),
-                               pw.l2TunnelPolicy().cP2InnerTag(),
-                               pw.l2TunnelPolicy().cP2OuterTag(),
-                               egressVlan,
-                               result.nextId);
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying policy for CP2");
-            return Result.ADDITION_ERROR;
-        }
-
-        result = deployPseudoWireTerm(pw.l2Tunnel(),
-                                       pw.l2TunnelPolicy().cP1(),
-                                       VlanId.NONE,
-                                       REV,
-                                      spinePw);
-
-        if (result != SUCCESS) {
-            log.info("Deploying process : Error in deploying pseudowire termination for CP2");
-            return Result.ADDITION_ERROR;
-        }
-
-        log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
-
-        // Populate stores
-        l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
-        l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
-
-        return Result.SUCCESS;
-    }
-
-    /**
-     * To deploy a number of pseudo wires.
-     * <p>
-     * Called ONLY when configuration changes, thus the check
-     * for the mastership of the device.
-     * <p>
-     * Only the master of CP1 will deploy this pseudowire.
-     *
-     * @param pwToAdd the set of pseudo wires to add
-     */
-    private void deploy(Set<DefaultL2TunnelDescription> pwToAdd) {
-
-        Result result;
-
-        for (DefaultL2TunnelDescription currentL2Tunnel : pwToAdd) {
-            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
-            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
-            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
-
-            // only the master of CP1 will program this pseudowire
-            if (!srManager.isMasterOf(cp1)) {
-                log.debug("Not the master of {}. Ignore pseudo wire deployment id={}", cp1, tunnelId);
-                continue;
-            }
-
-            try {
-                // differentiate between leaf-leaf pseudowires and leaf-spine
-                // and pass the appropriate flag in them.
-                if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
-                    !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
-                    log.warn("Can not deploy pseudowire from spine to spine!");
-                    result = Result.INTERNAL_ERROR;
-                } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
-                     srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
-                    log.info("Deploying a leaf-leaf pseudowire {}", tunnelId);
-                    result = deployPseudowire(currentL2Tunnel, false);
-                } else {
-                    log.info("Deploying a leaf-spine pseudowire {}", tunnelId);
-                    result = deployPseudowire(currentL2Tunnel, true);
-                }
-            } catch (DeviceConfigNotFoundException e) {
-                log.error("Exception caught when deploying pseudowire", e.toString());
-                result = Result.INTERNAL_ERROR;
-            }
-
-            switch (result) {
-                case INTERNAL_ERROR:
-                    log.warn("Could not deploy pseudowire {}, internal error!", tunnelId);
-                    break;
-                case WRONG_PARAMETERS:
-                    log.warn("Could not deploy pseudowire {}, wrong parameters!", tunnelId);
-                    break;
-                case ADDITION_ERROR:
-                    log.warn("Could not deploy pseudowire {}, error in populating rules!", tunnelId);
-                    break;
-                default:
-                    log.info("Pseudowire with {} succesfully deployed!", tunnelId);
-                    break;
-            }
-        }
-    }
+    void processPwaasConfigAdded(NetworkConfigEvent event);
 
     /**
      * Processes PWaaS Config updated event.
      *
      * @param event network config updated event
      */
-    public void processPwaasConfigUpdated(NetworkConfigEvent event) {
-        checkArgument(event.config().isPresent(),
-                "Config is not presented in PwaasConfigUpdated event {}", event);
-        checkArgument(event.prevConfig().isPresent(),
-                "PrevConfig is not presented in PwaasConfigUpdated event {}", event);
-
-        log.info("Pseudowire configuration updated.");
-
-        // We retrieve the old pseudo wires.
-        PwaasConfig prevConfig = (PwaasConfig) event.prevConfig().get();
-        Set<Long> prevPws = prevConfig.getPwIds();
-
-        // We retrieve the new pseudo wires.
-        PwaasConfig config = (PwaasConfig) event.config().get();
-        Set<Long> newPws = config.getPwIds();
-
-        // We compute the pseudo wires to update.
-        Set<Long> updPws = newPws.stream()
-                .filter(tunnelId -> prevPws.contains(tunnelId)
-                        && !config.getPwDescription(tunnelId).equals(prevConfig.getPwDescription(tunnelId)))
-                .collect(Collectors.toSet());
-
-        // The pseudo wires to remove.
-        Set<Long> rmvPWs = prevPws.stream()
-                .filter(tunnelId -> !newPws.contains(tunnelId)).collect(Collectors.toSet());
-
-        Set<DefaultL2TunnelDescription> pwToRemove = rmvPWs.stream()
-                .map(prevConfig::getPwDescription)
-                .collect(Collectors.toSet());
-        tearDown(pwToRemove);
-
-        // The pseudo wires to add.
-        Set<Long> addedPWs = newPws.stream()
-                .filter(tunnelId -> !prevPws.contains(tunnelId))
-                .collect(Collectors.toSet());
-        Set<DefaultL2TunnelDescription> pwToAdd = addedPWs.stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-        deploy(pwToAdd);
-
-
-        // The pseudo wires to update.
-        updPws.forEach(tunnelId -> updatePw(prevConfig.getPwDescription(tunnelId),
-                                            config.getPwDescription(tunnelId)));
-
-        log.info("Pseudowires removed : {}, Pseudowires updated : {}, Pseudowires added : {}", rmvPWs,
-                 updPws, addedPWs);
-    }
-
-    /**
-     * Helper function to update a pw.
-     * <p>
-     * Called upon configuration changes that update existing pseudowires and
-     * when links fail. Checking of mastership for CP1 is mandatory because it is
-     * called in multiple instances for both cases.
-     * <p>
-     * Meant to call asynchronously for various events, thus this call can not block and need
-     * to perform asynchronous operations.
-     * <p>
-     * For this reason error checking is omitted.
-     *
-     * @param oldPw the pseudo wire to remove
-     * @param newPw the pseudo wire to add
-     */
-    private void updatePw(DefaultL2TunnelDescription oldPw,
-                         DefaultL2TunnelDescription newPw) {
-        ConnectPoint oldCp1 = oldPw.l2TunnelPolicy().cP1();
-        long tunnelId = oldPw.l2Tunnel().tunnelId();
-
-        // only the master of CP1 will update this pseudowire
-        if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) {
-            log.debug("Not the master of {}. Ignore pseudo wire update id={}", oldCp1, tunnelId);
-            return;
-        }
-        // only determine if the new pseudowire is leaf-spine, because
-        // removal process is the same for both leaf-leaf and leaf-spine pws
-        boolean newPwSpine;
-        try {
-            newPwSpine = !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP1().deviceId()) ||
-                    !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP2().deviceId());
-        } catch (DeviceConfigNotFoundException e) {
-            // if exception is caught treat the new pw as leaf-leaf
-            newPwSpine = false;
-        }
-
-        // copy the variable here because we need to use it in lambda thus it needs to be final
-        boolean finalNewPwSpine = newPwSpine;
-
-        log.info("Updating pseudowire {}", oldPw.l2Tunnel().tunnelId());
-
-        // The async tasks to orchestrate the next and forwarding update
-        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> fwdPwFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revPwFuture = new CompletableFuture<>();
-
-        // first delete all information from our stores, we can not do it asynchronously
-        l2PolicyStore.remove(Long.toString(tunnelId));
-
-        // grab the old l2 tunnel from the store, since it carries information which is not exposed
-        // to the user configuration and set it to oldPw.
-        oldPw.setL2Tunnel(l2TunnelStore.get(Long.toString(tunnelId)).value());
-        VlanId transportVlan = l2TunnelStore.get(Long.toString(tunnelId)).value().transportVlan();
-        l2TunnelStore.remove(Long.toString(tunnelId));
-
-        // remove the reserved transport vlan, if one is used
-        if (!transportVlan.equals(UNTAGGED_TRANSPORT_VLAN)) {
-            vlanStore.remove(transportVlan);
-        }
-
-        // First we remove both policy.
-        log.debug("Start deleting fwd policy for {}", tunnelId);
-        VlanId egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP1OuterTag(),
-                                                 oldPw.l2TunnelPolicy().cP1InnerTag(),
-                                                 oldPw.l2TunnelPolicy().cP2OuterTag(),
-                                                 oldPw.l2TunnelPolicy().cP2InnerTag());
-        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP1(),
-                      oldPw.l2TunnelPolicy().cP1InnerTag(),
-                      oldPw.l2TunnelPolicy().cP1OuterTag(),
-                      egressVlan,
-                      fwdInitNextFuture,
-                      FWD);
-
-        log.debug("Update process : Start deleting rev policy for {}", tunnelId);
-        egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP2OuterTag(),
-                                          oldPw.l2TunnelPolicy().cP2InnerTag(),
-                                          oldPw.l2TunnelPolicy().cP1OuterTag(),
-                                          oldPw.l2TunnelPolicy().cP1InnerTag());
-        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP2(),
-                      oldPw.l2TunnelPolicy().cP2InnerTag(),
-                      oldPw.l2TunnelPolicy().cP2OuterTag(),
-                      egressVlan, revInitNextFuture,
-                      REV);
-
-        // Finally we remove both the tunnels.
-        fwdInitNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                log.debug("Update process : Fwd policy removed. " +
-                                  "Now remove fwd {} for {}", INITIATION, tunnelId);
-                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP1(), fwdTermNextFuture, FWD);
-            }
-        });
-        revInitNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                log.debug("Update process : Rev policy removed. " +
-                                  "Now remove rev {} for {}", INITIATION, tunnelId);
-                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP2(), revTermNextFuture, REV);
-            }
-        });
-        fwdTermNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                log.debug("Update process : Fwd {} removed. " +
-                                  "Now remove fwd {} for {}", INITIATION, TERMINATION, tunnelId);
-                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP2(),  fwdPwFuture, FWD);
-            }
-        });
-        revTermNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                log.debug("Update process : Rev {} removed. " +
-                                  "Now remove rev {} for {}", INITIATION, TERMINATION, tunnelId);
-                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP1(), revPwFuture, REV);
-            }
-        });
-
-        // get path here, need to use the same for fwd and rev direction
-        List<Link> path = getPath(newPw.l2TunnelPolicy().cP1(),
-                                   newPw.l2TunnelPolicy().cP2());
-        if (path == null) {
-            log.error("Update process : " +
-                             "No path between the connection points for pseudowire {}", newPw.l2Tunnel().tunnelId());
-            return;
-        }
-
-        Link fwdNextHop, revNextHop;
-        if (!finalNewPwSpine) {
-            if (path.size() != 2) {
-                log.error("Update process : Error, path between two leafs should have size of 2, for pseudowire {}",
-                         newPw.l2Tunnel().tunnelId());
-                return;
-            }
-            fwdNextHop = path.get(0);
-            revNextHop = reverseLink(path.get(1));
-        } else {
-            if (path.size() != 1) {
-                log.error("Update process : Error, path between leaf spine should equal to 1, for pseudowire {}",
-                         newPw.l2Tunnel().tunnelId());
-                return;
-            }
-            fwdNextHop = path.get(0);
-            revNextHop = reverseLink(path.get(0));
-        }
-
-        // set new path and transport vlan.
-        newPw.l2Tunnel().setPath(path);
-        newPw.l2Tunnel().setTransportVlan(determineTransportVlan(newPwSpine));
-
-        // At the end we install the updated PW.
-        fwdPwFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-
-                // Upgrade stores and book keeping information, need to move this here
-                // cause this call is asynchronous.
-                l2PolicyStore.put(Long.toString(tunnelId), newPw.l2TunnelPolicy());
-                l2TunnelStore.put(Long.toString(tunnelId), newPw.l2Tunnel());
-
-                log.debug("Update process : Deploying new fwd pw for {}", tunnelId);
-                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP1(),
-                                                           newPw.l2TunnelPolicy().cP2(), FWD,
-                                                           fwdNextHop, finalNewPwSpine);
-                if (lamdaResult != SUCCESS) {
-                    return;
-                }
-
-                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP1OuterTag(),
-                                                          newPw.l2TunnelPolicy().cP1InnerTag(),
-                                                           newPw.l2TunnelPolicy().cP2OuterTag(),
-                                                          newPw.l2TunnelPolicy().cP2InnerTag());
-
-                lamdaResult = deployPolicy(tunnelId, newPw.l2TunnelPolicy().cP1(),
-                                            newPw.l2TunnelPolicy().cP1InnerTag(),
-                                           newPw.l2TunnelPolicy().cP1OuterTag(),
-                                            egressVlanId, lamdaResult.nextId);
-                if (lamdaResult != SUCCESS) {
-                    return;
-                }
-                deployPseudoWireTerm(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP2(),
-                                      VlanId.NONE, FWD, finalNewPwSpine);
-
-            }
-        });
-        revPwFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-
-                log.debug("Update process : Deploying new rev pw for {}", tunnelId);
-                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(),
-                                                           newPw.l2TunnelPolicy().cP2(),
-                                                           newPw.l2TunnelPolicy().cP1(),
-                                                           REV,
-                                                           revNextHop, finalNewPwSpine);
-                if (lamdaResult != SUCCESS) {
-                    return;
-                }
-
-                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP2OuterTag(),
-                                                           newPw.l2TunnelPolicy().cP2InnerTag(),
-                                                           newPw.l2TunnelPolicy().cP1OuterTag(),
-                                                           newPw.l2TunnelPolicy().cP1InnerTag());
-                lamdaResult = deployPolicy(tunnelId,
-                                            newPw.l2TunnelPolicy().cP2(),
-                                            newPw.l2TunnelPolicy().cP2InnerTag(),
-                                            newPw.l2TunnelPolicy().cP2OuterTag(),
-                                            egressVlanId,
-                                            lamdaResult.nextId);
-                if (lamdaResult != SUCCESS) {
-                    return;
-                }
-                deployPseudoWireTerm(newPw.l2Tunnel(),
-                                      newPw.l2TunnelPolicy().cP1(),
-                                      VlanId.NONE,
-                                      REV, finalNewPwSpine);
-            }
-        });
-    }
+    void processPwaasConfigUpdated(NetworkConfigEvent event);
 
     /**
      * Processes Pwaas Config removed event.
      *
      * @param event network config removed event
      */
-    public void processPwaasConfigRemoved(NetworkConfigEvent event) {
-        checkArgument(event.prevConfig().isPresent(),
-                "PrevConfig is not presented in PwaasConfigRemoved event {}", event);
-
-        log.info("Network event : Pseudowire configuration removed!");
-        PwaasConfig config = (PwaasConfig) event.prevConfig().get();
-
-        Set<DefaultL2TunnelDescription> pwToRemove = config
-                .getPwIds()
-                .stream()
-                .map(config::getPwDescription)
-                .collect(Collectors.toSet());
-
-        // We teardown all the pseudo wire deployed
-        tearDown(pwToRemove);
-    }
-
-    /**
-     * Helper function for removing a single pseudowire.
-     * <p>
-     * No mastership of CP1 is checked, because it can be called from
-     * the CLI for removal of pseudowires.
-     *
-     * @param l2TunnelId the id of the pseudowire to tear down
-     * @return Returns SUCCESS if no error is obeserved or an appropriate
-     * error on a failure
-     */
-    private Result tearDownPseudowire(long l2TunnelId) {
-
-        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
-
-        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
-
-        if (l2TunnelId == 0) {
-            log.warn("Removal process : Tunnel id cannot be 0");
-            return Result.WRONG_PARAMETERS;
-        }
-
-        // check existence of tunnels/policy in the store, if one is missing abort!
-        Versioned<DefaultL2Tunnel> l2TunnelVersioned = l2TunnelStore.get(Long.toString(l2TunnelId));
-        Versioned<DefaultL2TunnelPolicy> l2TunnelPolicyVersioned = l2PolicyStore.get(Long.toString(l2TunnelId));
-        if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
-            log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
-            return Result.REMOVAL_ERROR;
-        }
-
-        DefaultL2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(),
-                                                                               l2TunnelPolicyVersioned.value());
-
-        // remove the tunnels and the policies from the store
-        l2PolicyStore.remove(Long.toString(l2TunnelId));
-        l2TunnelStore.remove(Long.toString(l2TunnelId));
-
-        // remove the reserved transport vlan
-        if (!pwToRemove.l2Tunnel().transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
-            vlanStore.remove(pwToRemove.l2Tunnel().transportVlan());
-        }
-
-        log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);
-
-        VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                                                 pwToRemove.l2TunnelPolicy().cP1InnerTag(),
-                                                 pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                                                 pwToRemove.l2TunnelPolicy().cP2InnerTag());
-        deletePolicy(l2TunnelId,
-                      pwToRemove.l2TunnelPolicy().cP1(),
-                      pwToRemove.l2TunnelPolicy().cP1InnerTag(),
-                      pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                      egressVlan,
-                      fwdInitNextFuture,
-                      FWD);
-
-        fwdInitNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                // Finally we will tear down the pseudo wire.
-                tearDownPseudoWireInit(l2TunnelId,
-                                        pwToRemove.l2TunnelPolicy().cP1(),
-                                        fwdTermNextFuture,
-                                        FWD);
-            }
-        });
-
-        fwdTermNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
-                                        pwToRemove.l2TunnelPolicy().cP2(),
-                                        null,
-                                        FWD);
-            }
-        });
-
-        log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);
-
-        egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                                          pwToRemove.l2TunnelPolicy().cP2InnerTag(),
-                                          pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                                          pwToRemove.l2TunnelPolicy().cP1InnerTag());
-
-        // We do the same operations on the reverse side.
-        deletePolicy(l2TunnelId,
-                      pwToRemove.l2TunnelPolicy().cP2(),
-                      pwToRemove.l2TunnelPolicy().cP2InnerTag(),
-                      pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                      egressVlan,
-                      revInitNextFuture,
-                      REV);
-
-        revInitNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                tearDownPseudoWireInit(l2TunnelId,
-                                        pwToRemove.l2TunnelPolicy().cP2(),
-                                        revTermNextFuture,
-                                        REV);
-            }
-        });
-
-        revTermNextFuture.thenAcceptAsync(status -> {
-            if (status == null) {
-                tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
-                                        pwToRemove.l2TunnelPolicy().cP1(),
-                                        null,
-                                        REV);
-            }
-        });
-
-        return Result.SUCCESS;
-    }
+    void processPwaasConfigRemoved(NetworkConfigEvent event);
 
     /**
      * Helper function to handle the pw removal.
      * <p>
-     * This method checks for the mastership of the device because it is
+     * This method should for the mastership of the device because it is
      * used only from network configuration updates, thus we only want
      * one instance only to program each pseudowire.
      *
      * @param pwToRemove the pseudo wires to remove
      */
-    public void tearDown(Set<DefaultL2TunnelDescription> pwToRemove) {
-
-        Result result;
-
-        // We remove all the pw in the configuration file.
-        for (DefaultL2TunnelDescription currentL2Tunnel : pwToRemove) {
-            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
-            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
-            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
-
-            // only the master of CP1 will program this pseudowire
-            if (!srManager.isMasterOf(cp1)) {
-                log.debug("Not the master of {}. Ignore pseudo wire removal id={}", cp1, tunnelId);
-                continue;
-            }
-
-            // no need to differentiate here between leaf-leaf and leaf-spine, because
-            // the only change is in the groups, which we do not remove either way
-            log.info("Removing pseudowire {}", tunnelId);
-
-            result = tearDownPseudowire(tunnelId);
-            switch (result) {
-                case WRONG_PARAMETERS:
-                    log.warn("Error in supplied parameters for the pseudowire removal with tunnel id {}!",
-                            tunnelId);
-                    break;
-                case REMOVAL_ERROR:
-                    log.warn("Error in pseudowire removal with tunnel id {}!", tunnelId);
-                    break;
-                default:
-                    log.warn("Pseudowire with tunnel id {} was removed successfully", tunnelId);
-            }
-        }
-    }
-
-    /**
-     * Handles the policy establishment which consists in
-     * create the filtering and forwarding objectives related
-     * to the initiation and termination.
-     *
-     * @param tunnelId     the tunnel id
-     * @param ingress      the ingress point
-     * @param ingressInner the ingress inner tag
-     * @param ingressOuter the ingress outer tag
-     * @param nextId       the next objective id
-     * @param egressVlan   Vlan-id to set, depends on ingress vlan
-     *                     combinations. For example, if pw is double tagged
-     *                     then this is the value of the outer vlan, if single
-     *                     tagged then it is the new value of the single tag.
-     *                     Should be None for untagged traffic.
-     * @return the result of the operation
-     */
-    private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
-                                VlanId ingressOuter, VlanId egressVlan, int nextId) {
-
-        List<Objective> objectives = Lists.newArrayList();
-        // We create the forwarding objective for supporting
-        // the l2 tunnel.
-        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
-        // We create and add objective context.
-        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
-                                                                log.debug("FwdObj for tunnel {} populated", tunnelId),
-                                                               (objective, error) ->
-                                                                log.warn("Failed to populate fwdrObj " +
-                                                                                 "for tunnel {}", tunnelId, error));
-        objectives.add(fwdBuilder.add(context));
-
-        // We create the filtering objective to define the
-        // permit traffic in the switch
-        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
-
-        // We add the metadata.
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
-                .builder()
-                .setTunnelId(tunnelId)
-                .setVlanId(egressVlan);
-        filtBuilder.withMeta(treatment.build());
-
-        // We create and add objective context.
-        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
-                                              (objective, error) -> log.warn("Failed to populate filterObj for " +
-                                                                                     "tunnel {}", tunnelId, error));
-        objectives.add(filtBuilder.add(context));
-
-        for (Objective objective : objectives) {
-            if (objective instanceof ForwardingObjective) {
-                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
-                log.debug("Creating new FwdObj for initiation NextObj with id={} for tunnel {}", nextId, tunnelId);
-            } else {
-                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
-                log.debug("Creating new FiltObj for tunnel {}", tunnelId);
-            }
-        }
-        return SUCCESS;
-    }
-
-    /**
-     * Handles the tunnel establishment which consists in
-     * create the next objectives related to the initiation.
-     *
-     * @param l2Tunnel  the tunnel to deploy
-     * @param ingress   the ingress connect point
-     * @param egress    the egress connect point
-     * @param direction the direction of the pw
-     * @param spinePw if the pseudowire involves a spine switch
-     * @return the result of the operation
-     */
-    private Result deployPseudoWireInit(DefaultL2Tunnel l2Tunnel, ConnectPoint ingress,
-                                        ConnectPoint egress, Direction direction, Link nextHop, boolean spinePw) {
-
-        if (nextHop == null) {
-            log.warn("No path between ingress and egress cps for tunnel {}", l2Tunnel.tunnelId());
-            return WRONG_PARAMETERS;
-        }
-
-        // We create the next objective without the metadata
-        // context and id. We check if it already exists in the
-        // store. If not we store as it is in the store.
-        NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION,
-                                                                         nextHop.src(),
-                                                                         nextHop.dst(),
-                                                                         l2Tunnel,
-                                                                         egress.deviceId(),
-                                                                         spinePw);
-
-        if (nextObjectiveBuilder == null) {
-            return INTERNAL_ERROR;
-        }
-        // We set the metadata. We will use this metadata
-        // to inform the driver we are doing a l2 tunnel.
-        TrafficSelector metadata = DefaultTrafficSelector
-                .builder()
-                .matchTunnelId(l2Tunnel.tunnelId())
-                .build();
-        nextObjectiveBuilder.withMeta(metadata);
-        int nextId = srManager.flowObjectiveService.allocateNextId();
-        if (nextId < 0) {
-            log.warn("Not able to allocate a next id for initiation");
-            return INTERNAL_ERROR;
-        }
-        nextObjectiveBuilder.withId(nextId);
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
-        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
-                                                                 log.debug("Initiation l2 tunnel rule " +
-                                                                                   "for {} populated",
-                                                                           l2Tunnel.tunnelId()),
-                                                               (objective, error) ->
-                                                                       log.warn("Failed to populate Initiation " +
-                                                                                        "l2 tunnel rule for {}: {}",
-                                                                                l2Tunnel.tunnelId(), error));
-        NextObjective nextObjective = nextObjectiveBuilder.add(context);
-        srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
-        log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}",
-                  l2Tunnel.tunnelId(), nextObjective.id());
-        Result result = SUCCESS;
-        result.nextId = nextObjective.id();
-        return result;
-    }
-
-    /**
-     * Handles the tunnel termination, which consists in the creation
-     * of a forwarding objective and a next objective.
-     *
-     * @param l2Tunnel   the tunnel to terminate
-     * @param egress     the egress point
-     * @param egressVlan the expected vlan at egress
-     * @param direction  the direction
-     * @param spinePw if the pseudowire involves a spine switch
-     * @return the result of the operation
-     */
-    private Result deployPseudoWireTerm(DefaultL2Tunnel l2Tunnel, ConnectPoint egress,
-                                        VlanId egressVlan, Direction direction, boolean spinePw) {
-
-        // We create the group relative to the termination.
-        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
-                                                                         l2Tunnel, egress.deviceId(),
-                                                                         spinePw);
-        if (nextObjectiveBuilder == null) {
-            return INTERNAL_ERROR;
-        }
-        TrafficSelector metadata = DefaultTrafficSelector
-                .builder()
-                .matchVlanId(egressVlan)
-                .build();
-        nextObjectiveBuilder.withMeta(metadata);
-        int nextId = srManager.flowObjectiveService.allocateNextId();
-        if (nextId < 0) {
-            log.warn("Not able to allocate a next id for initiation");
-            return INTERNAL_ERROR;
-        }
-        nextObjectiveBuilder.withId(nextId);
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
-        ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("Termination l2 tunnel rule " +
-                                                                                        "for {} populated",
-                                                                                        l2Tunnel.tunnelId()),
-                                                               (objective, error) -> log.warn("Failed to populate " +
-                                                                                              "termination l2 tunnel " +
-                                                                                              "rule for {}: {}",
-                                                                                              l2Tunnel.tunnelId(),
-                                                                                              error));
-        NextObjective nextObjective = nextObjectiveBuilder.add(context);
-        srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
-        log.debug("Termination next objective for {} not found. Creating new NextObj with id={}",
-                  l2Tunnel.tunnelId(), nextObjective.id());
-
-        // We create the flow relative to the termination.
-        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(),
-                                                                        egress.port(), nextObjective.id());
-        context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
-                                                                       l2Tunnel.tunnelId()),
-                                              (objective, error) -> log.warn("Failed to populate fwdrObj" +
-                                                                             " for tunnel termination {}",
-                                                                             l2Tunnel.tunnelId(), error));
-        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
-        log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
-                  nextId, l2Tunnel.tunnelId());
-
-        if (spinePw) {
-
-            // determine the input port at the
-            PortNumber inPort;
-
-            if (egress.deviceId().
-                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
-                    inPort = l2Tunnel.pathUsed().get(0).dst().port();
-            } else {
-                    inPort = l2Tunnel.pathUsed().get(0).src().port();
-            }
-
-            MacAddress dstMac;
-            try {
-                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
-            } catch (Exception e) {
-                log.info("Device not found in configuration, no programming of MAC address");
-                dstMac = null;
-            }
-
-            log.info("Populating filtering objective for pseudowire transport" +
-                             " with vlan = {}, port = {}, mac = {}",
-                     l2Tunnel.transportVlan(),
-                     inPort,
-                     dstMac);
-            FilteringObjective.Builder filteringObjectiveBuilder =
-                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
-            context = new DefaultObjectiveContext(( objective ) ->
-                                                          log.debug("Special filtObj for  " + "for {} populated",
-                                                                    l2Tunnel.tunnelId()),
-                                                  ( objective, error ) ->
-                                                          log.warn("Failed to populate " +
-                                                                           "special filtObj " +
-                                                                           "rule for {}: {}",
-                                                                                   l2Tunnel.tunnelId(), error));
-            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-            filteringObjectiveBuilder.withMeta(treatment.build());
-            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.add(context));
-            log.debug("Creating new special FiltObj for termination point with tunnel {} for port {}",
-                      l2Tunnel.tunnelId(),
-                      inPort);
-        }
-
-        return SUCCESS;
-    }
-
-
-    /**
-     * Creates the filtering objective according to a given port and vlanid.
-     *
-     * @param inPort   the in port
-     * @param vlanId the inner vlan tag
-     * @return the filtering objective
-     */
-    private FilteringObjective.Builder createNormalPipelineFiltObjective(PortNumber inPort,
-                                                                         VlanId vlanId,
-                                                                         MacAddress dstMac) {
-
-        log.info("Creating filtering objective for pseudowire transport with vlan={}, port={}, mac={}",
-                 vlanId,
-                 inPort,
-                 dstMac);
-        FilteringObjective.Builder fwdBuilder = DefaultFilteringObjective
-                .builder()
-                .withKey(Criteria.matchInPort(inPort))
-                .addCondition(Criteria.matchVlanId(vlanId))
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .permit()
-                .fromApp(srManager.appId());
-
-        if (dstMac != null) {
-            fwdBuilder.addCondition(Criteria.matchEthDst(dstMac));
-        }
-
-        return fwdBuilder;
-    }
-
-    /**
-     * Creates the filtering objective according to a given policy.
-     *
-     * @param inPort   the in port
-     * @param innerTag the inner vlan tag
-     * @param outerTag the outer vlan tag
-     * @return the filtering objective
-     */
-    private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {
-
-        log.info("Creating filtering objective for vlans {} / {}", outerTag, innerTag);
-        return DefaultFilteringObjective
-                .builder()
-                .withKey(Criteria.matchInPort(inPort))
-                .addCondition(Criteria.matchInnerVlanId(innerTag))
-                .addCondition(Criteria.matchVlanId(outerTag))
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .permit()
-                .fromApp(srManager.appId());
-    }
-
-    /**
-     * Creates the forwarding objective for the termination.
-     *
-     * @param pwLabel    the pseudo wire label
-     * @param tunnelId   the tunnel id
-     * @param egressPort the egress port
-     * @param nextId     the next step
-     * @return the forwarding objective to support the termination
-     */
-    private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
-                                                               PortNumber egressPort, int nextId) {
-
-        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
-        TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
-        // The flow has to match on the pw label and bos
-        trafficSelector.matchEthType(Ethernet.MPLS_UNICAST);
-        trafficSelector.matchMplsLabel(pwLabel);
-        trafficSelector.matchMplsBos(true);
-        // The flow has to decrement ttl, restore ttl in
-        // pop mpls, set tunnel id and port.
-        trafficTreatment.decMplsTtl();
-        trafficTreatment.copyTtlIn();
-        trafficTreatment.popMpls();
-        trafficTreatment.setTunnelId(tunnelId);
-        trafficTreatment.setOutput(egressPort);
-
-        return DefaultForwardingObjective
-                .builder()
-                .fromApp(srManager.appId())
-                .makePermanent()
-                .nextStep(nextId)
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .withSelector(trafficSelector.build())
-                .withTreatment(trafficTreatment.build())
-                .withFlag(VERSATILE);
-    }
-
-    /**
-     * Creates the forwarding objective for the initiation.
-     *
-     * @param tunnelId the tunnel id
-     * @param inPort   the input port
-     * @param nextId   the next step
-     * @return the forwarding objective to support the initiation.
-     */
-    private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {
-
-        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
-
-        // The flow has to match on the mpls logical
-        // port and the tunnel id.
-        trafficSelector.matchTunnelId(tunnelId);
-        trafficSelector.matchInPort(inPort);
-
-        return DefaultForwardingObjective
-                .builder()
-                .fromApp(srManager.appId())
-                .makePermanent()
-                .nextStep(nextId)
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .withSelector(trafficSelector.build())
-                .withFlag(VERSATILE);
-
-    }
-
-    /**
-     * Creates the next objective according to a given
-     * pipeline. We don't set the next id and we don't
-     * create the final meta to check if we are re-using
-     * the same next objective for different tunnels.
-     *
-     * @param pipeline the pipeline to support
-     * @param srcCp    the source port
-     * @param dstCp    the destination port
-     * @param l2Tunnel the tunnel to support
-     * @param egressId the egress device id
-     * @param spinePw if the pw involves a spine switch
-     * @return the next objective to support the pipeline
-     */
-    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
-                                                      ConnectPoint dstCp,  DefaultL2Tunnel l2Tunnel,
-                                                      DeviceId egressId, boolean spinePw) {
-        NextObjective.Builder nextObjBuilder;
-        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-        if (pipeline == INITIATION) {
-            nextObjBuilder = DefaultNextObjective
-                    .builder()
-                    .withType(NextObjective.Type.SIMPLE)
-                    .fromApp(srManager.appId());
-            // The pw label is the bottom of stack. It has to
-            // be different -1.
-            if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
-                log.warn("Pw label not configured");
-                return null;
-            }
-            treatmentBuilder.pushMpls();
-            treatmentBuilder.setMpls(l2Tunnel.pwLabel());
-            treatmentBuilder.setMplsBos(true);
-            treatmentBuilder.copyTtlOut();
-
-            // If the inter-co label is present we have to set the label.
-            if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
-                treatmentBuilder.pushMpls();
-                treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
-                treatmentBuilder.setMplsBos(false);
-                treatmentBuilder.copyTtlOut();
-            }
-
-            // if pw is leaf-to-leaf we need to
-            // add the routing label also
-            if (!spinePw) {
-                // We retrieve the sr label from the config
-                // specific for pseudowire traffic
-                // using the egress leaf device id.
-                MplsLabel srLabel;
-                try {
-                    srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
-
-                } catch (DeviceConfigNotFoundException e) {
-                    log.warn("Sr label for pw traffic not configured");
-                    return null;
-                }
-
-                treatmentBuilder.pushMpls();
-                treatmentBuilder.setMpls(srLabel);
-                treatmentBuilder.setMplsBos(false);
-                treatmentBuilder.copyTtlOut();
-            }
-
-            // We have to rewrite the src and dst mac address.
-            MacAddress ingressMac;
-            try {
-                ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn("Was not able to find the ingress mac");
-                return null;
-            }
-            treatmentBuilder.setEthSrc(ingressMac);
-            MacAddress neighborMac;
-            try {
-                neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn("Was not able to find the neighbor mac");
-                return null;
-            }
-            treatmentBuilder.setEthDst(neighborMac);
-
-            // if not a leaf-spine pw we need to POP the vlan at the output
-            // since we carry this traffic untagged.
-            if (!spinePw) {
-                treatmentBuilder.popVlan();
-            }
-        } else {
-            // We create the next objective which
-            // will be a simple l2 group.
-            nextObjBuilder = DefaultNextObjective
-                    .builder()
-                    .withType(NextObjective.Type.SIMPLE)
-                    .fromApp(srManager.appId());
-        }
-
-        // set the appropriate transport vlan
-        treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
-        treatmentBuilder.setOutput(srcCp.port());
-        nextObjBuilder.addTreatment(treatmentBuilder.build());
-        return nextObjBuilder;
-    }
-
-    /**
-     * Reverses a link.
-     *
-     * @param link link to be reversed
-     * @return the reversed link
-     */
-    private Link reverseLink(Link link) {
-
-        DefaultLink.Builder linkBuilder = DefaultLink.builder();
-
-        linkBuilder.src(link.dst());
-        linkBuilder.dst(link.src());
-        linkBuilder.type(link.type());
-        linkBuilder.providerId(link.providerId());
-
-        return linkBuilder.build();
-    }
-
-    /**
-     * Returns the path betwwen two connect points.
-     *
-     * @param srcCp source connect point
-     * @param dstCp destination connect point
-     * @return the path
-     */
-    private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {
-        /* TODO We retrieve a set of paths in case of a link failure, what happens
-         * if the TopologyService gets the link notification AFTER us and has not updated the paths?
-         *
-         * TODO This has the potential to act on old topology.
-         * Maybe we should make SRManager be a listener on topology events instead raw link events.
-         */
-        Set<Path> paths = srManager.topologyService.getPaths(
-                srManager.topologyService.currentTopology(),
-                srcCp.deviceId(), dstCp.deviceId());
-
-        log.debug("Paths obtained from topology service {}", paths);
-
-        // We randomly pick a path.
-        if (paths.isEmpty()) {
-            return null;
-        }
-        int size = paths.size();
-        int index = RandomUtils.nextInt(0, size);
-
-        List<Link> result = Iterables.get(paths, index).links();
-        log.debug("Randomly picked a path {}", result);
-
-        return result;
-    }
-
-    /**
-     * Deletes a given policy using the parameter supplied.
-     *
-     * @param tunnelId     the tunnel id
-     * @param ingress      the ingress point
-     * @param ingressInner the ingress inner vlan id
-     * @param ingressOuter the ingress outer vlan id
-     * @param future       to perform the async operation
-     * @param direction    the direction: forward or reverse
-     */
-    private void deletePolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner, VlanId ingressOuter,
-                              VlanId egressVlan, CompletableFuture<ObjectiveError> future, Direction direction) {
-
-        String key = generateKey(tunnelId, direction);
-        if (!l2InitiationNextObjStore.containsKey(key)) {
-            log.warn("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
-        int nextId = nextObjective.id();
-        List<Objective> objectives = Lists.newArrayList();
-        // We create the forwarding objective.
-        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous fwdObj for policy {} removed", tunnelId);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        objectives.add(fwdBuilder.remove(context));
-        // We create the filtering objective to define the
-        // permit traffic in the switch
-        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
-                .builder()
-                .setTunnelId(tunnelId)
-                .setVlanId(egressVlan);
-        filtBuilder.withMeta(treatment.build());
-        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for policy {} revoked", tunnelId),
-                                              (objective, error) ->
-                                                      log.warn("Failed to revoke filterObj for policy {}",
-                                                               tunnelId, error));
-        objectives.add(filtBuilder.remove(context));
-
-        for (Objective objective : objectives) {
-            if (objective instanceof ForwardingObjective) {
-                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
-            } else {
-                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
-            }
-        }
-    }
-
-    /**
-     * Deletes the pseudo wire initiation.
-     *
-     * @param l2TunnelId the tunnel id
-     * @param ingress    the ingress connect point
-     * @param future     to perform an async operation
-     * @param direction  the direction: reverse of forward
-     */
-    private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
-                                        CompletableFuture<ObjectiveError> future, Direction direction) {
-
-        String key = generateKey(l2TunnelId, direction);
-        if (!l2InitiationNextObjStore.containsKey(key)) {
-            log.info("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
-
-        // un-comment in case you want to delete groups used by the pw
-        // however, this will break the update of pseudowires cause the L2 interface group can
-        // not be deleted (it is referenced by other groups)
-        /*
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous {} next for {} removed", INITIATION, key);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous {} next for {}: {}", INITIATION, key, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        srManager.flowObjectiveService.next(ingress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
-        */
-
-        future.complete(null);
-        l2InitiationNextObjStore.remove(key);
-    }
-
-    /**
-     * Deletes the pseudo wire termination.
-     *
-     * @param l2Tunnel  the tunnel
-     * @param egress    the egress connect point
-     * @param future    the async task
-     * @param direction the direction of the tunnel
-     */
-    private void tearDownPseudoWireTerm(DefaultL2Tunnel l2Tunnel,
-                                        ConnectPoint egress,
-                                        CompletableFuture<ObjectiveError> future,
-                                        Direction direction) {
-
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        if (!l2TerminationNextObjStore.containsKey(key)) {
-            log.info("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-        NextObjective nextObjective = l2TerminationNextObjStore.get(key).value();
-        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(),
-                                                                        l2Tunnel.tunnelId(),
-                                                                        egress.port(),
-                                                                        nextObjective.id());
-        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
-                                                                       log.debug("FwdObj for {} {}, " +
-                                                                                         "direction {} removed",
-                                                                                        TERMINATION,
-                                                                                        l2Tunnel.tunnelId(),
-                                                                                        direction),
-                                                               (objective, error) ->
-                                                                       log.warn("Failed to remove fwdObj " +
-                                                                                        "for {} {}" +
-                                                                                        ", direction {}",
-                                                                                TERMINATION,
-                                                                                l2Tunnel.tunnelId(),
-                                                                                error,
-                                                                                direction));
-        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.remove(context));
-
-        // un-comment in case you want to delete groups used by the pw
-        // however, this will break the update of pseudowires cause the L2 interface group can
-        // not be deleted (it is referenced by other groups)
-        /*
-        context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous {} next for {} removed", TERMINATION, key);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous {} next for {}: {}", TERMINATION, key, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        srManager.flowObjectiveService.next(egress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
-        */
-
-        // delete the extra filtering objective for terminating
-        // spine-spine pws
-        if (!l2Tunnel.transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
-
-            // determine the input port at the
-            PortNumber inPort;
-
-            if (egress.deviceId().
-                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
-                inPort = l2Tunnel.pathUsed().get(0).dst().port();
-            } else {
-                inPort = l2Tunnel.pathUsed().get(0).src().port();
-            }
-
-            MacAddress dstMac;
-            try {
-                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
-            } catch (Exception e) {
-                log.info("Device not found in configuration, no programming of MAC address");
-                dstMac = null;
-            }
-
-            log.info("Removing filtering objective for pseudowire transport" +
-                             " with vlan = {}, port = {}, mac = {}",
-                     l2Tunnel.transportVlan(),
-                     inPort,
-                     dstMac);
-            FilteringObjective.Builder filteringObjectiveBuilder =
-                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
-            context = new DefaultObjectiveContext(( objective ) ->
-                                                          log.debug("Special filtObj for  " + "for {} removed",
-                                                                    l2Tunnel.tunnelId()), ( objective, error ) ->
-                    log.warn("Failed to populate " + "special filtObj " +
-                                     "rule for {}: {}", l2Tunnel.tunnelId(), error));
-            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-            filteringObjectiveBuilder.withMeta(treatment.build());
-            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.remove(context));
-            log.debug("Removing special FiltObj for termination point with tunnel {} for port {}",
-                      l2Tunnel.tunnelId(),
-                      inPort);
-        }
-
-        l2TerminationNextObjStore.remove(key);
-        future.complete(null);
-    }
-
-    /**
-     * Utilities to generate pw key.
-     *
-     * @param tunnelId  the tunnel id
-     * @param direction the direction of the pw
-     * @return the key of the store
-     */
-    private String generateKey(long tunnelId, Direction direction) {
-        return String.format("%s-%s", tunnelId, direction);
-    }
+    void tearDown(Set<L2TunnelDescription> pwToRemove);
 
     /**
      * Pwaas pipelines.
      */
-    protected enum Pipeline {
+    enum Pipeline {
         /**
          * The initiation pipeline.
          */
@@ -1758,7 +95,7 @@
     /**
      * Enum helper to carry results of various operations.
      */
-    public enum Result {
+    enum Result {
         /**
          * Happy ending scenario.
          */
@@ -1792,7 +129,7 @@
 
         private final int code;
         private final String description;
-        private int nextId;
+        public int nextId;
 
         Result(int code, String description) {
             this.code = code;
@@ -1812,7 +149,7 @@
     /**
      * Enum helper for handling the direction of the pw.
      */
-    public enum Direction {
+    enum Direction {
         /**
          * The forward direction of the pseudo wire.
          */
@@ -1821,5 +158,4 @@
          */
         REV
     }
-
 }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
new file mode 100644
index 0000000..17be45b
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.segmentrouting.pwaas;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+
+public interface L2TunnelPolicy {
+
+    /**
+     * Returns the first connect point of the policy.
+     *
+     * @return first connect point
+     */
+    ConnectPoint cP1();
+
+    /**
+     * Returns the second connect point of the policy.
+     *
+     * @return second connect point
+     */
+    ConnectPoint cP2();
+
+    /**
+     * Returns the cP1 inner vlan tag of the policy.
+     *
+     * @return cP1 inner vlan tag
+     */
+    VlanId cP1InnerTag();
+
+    /**
+     * Returns the cP1 outer vlan tag of the policy.
+     *
+     * @return cP1 outer vlan tag
+     */
+    VlanId cP1OuterTag();
+
+    /**
+     * Returns the cP2 inner vlan tag of the policy.
+     *
+     * @return cP2 inner vlan tag
+     */
+    VlanId cP2InnerTag();
+
+    /**
+     * Returns the cP2 outer vlan tag of the policy.
+     *
+     * @return cP2 outer vlan tag
+     */
+    VlanId cP2OuterTag();
+
+    /**
+     * Returns the tunnel ID of the policy.
+     *
+     * @return Tunnel ID
+     */
+    long tunnelId();
+}
