[VOL-3836] Extract the OLT pipeliners from ONOS

Change-Id: I1a11000b1e92148b5d5230c311202ba4abbb2ca8
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java
deleted file mode 100644
index 667d8cf..0000000
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * 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.driver.pipeline;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.NextGroup;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.IPProtocolCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveStore;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.DefaultGroupDescription;
-import org.onosproject.net.group.DefaultGroupKey;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.group.GroupDescription;
-import org.onosproject.net.group.GroupEvent;
-import org.onosproject.net.group.GroupKey;
-import org.onosproject.net.group.GroupListener;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.StorageService;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.Iterator;
-
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-
-public class NokiaOltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
-    private static final Integer QQ_TABLE = 1;
-    private static final short MCAST_VLAN = 4000;
-    private static final String OLTCOOKIES = "olt-cookies-must-be-unique";
-    private static final int EAPOL_FLOW_PRIORITY = 1200;
-    private final Logger log = getLogger(getClass());
-
-    private ServiceDirectory serviceDirectory;
-    private FlowRuleService flowRuleService;
-    private GroupService groupService;
-    private CoreService coreService;
-    private StorageService storageService;
-
-    private DeviceId deviceId;
-    private ApplicationId appId;
-
-
-    protected FlowObjectiveStore flowObjectiveStore;
-
-    private Cache<GroupKey, NextObjective> pendingGroups;
-
-    protected static KryoNamespace appKryo = new KryoNamespace.Builder()
-            .register(KryoNamespaces.API)
-            .register(GroupKey.class)
-            .register(DefaultGroupKey.class)
-            .register(OLTPipelineGroup.class)
-            .build("OltPipeline");
-    @Override
-    public void init(DeviceId deviceId, PipelinerContext context) {
-        log.debug("Initiate OLT pipeline");
-        this.serviceDirectory = context.directory();
-        this.deviceId = deviceId;
-
-        flowRuleService = serviceDirectory.get(FlowRuleService.class);
-        coreService = serviceDirectory.get(CoreService.class);
-        groupService = serviceDirectory.get(GroupService.class);
-        flowObjectiveStore = context.store();
-        storageService = serviceDirectory.get(StorageService.class);
-
-        appId = coreService.registerApplication(
-                "org.onosproject.driver.OLTPipeline");
-
-
-        pendingGroups = CacheBuilder.newBuilder()
-                .expireAfterWrite(20, TimeUnit.SECONDS)
-                .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
-                    if (notification.getCause() == RemovalCause.EXPIRED) {
-                        fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
-                    }
-                }).build();
-
-        groupService.addListener(new InnerGroupListener());
-
-    }
-
-    @Override
-    public void filter(FilteringObjective filter) {
-        Instructions.OutputInstruction output;
-
-        if (filter.meta() != null && !filter.meta().immediate().isEmpty()) {
-            output = (Instructions.OutputInstruction) filter.meta().immediate().stream()
-                    .filter(t -> t.type().equals(Instruction.Type.OUTPUT))
-                    .limit(1)
-                    .findFirst().get();
-
-            if (output == null || !output.port().equals(PortNumber.CONTROLLER)) {
-                log.error("OLT can only filter packet to controller");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-        } else {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        if (filter.key().type() != Criterion.Type.IN_PORT) {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        EthTypeCriterion ethType = (EthTypeCriterion)
-                filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE);
-
-        if (ethType == null) {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) {
-            provisionEapol(filter, ethType, output);
-        } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) {
-            IPProtocolCriterion ipProto = (IPProtocolCriterion)
-                    filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
-            if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) {
-                provisionIgmp(filter, ethType, ipProto, output);
-            } else {
-                log.error("OLT can only filter igmp");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-            }
-        } else {
-            log.error("OLT can only filter eapol and igmp");
-            fail(filter, ObjectiveError.UNSUPPORTED);
-        }
-
-    }
-
-    private void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
-        FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-        switch (objective.op()) {
-
-            case ADD:
-                flowBuilder.add(ruleBuilder.build());
-                break;
-            case REMOVE:
-                flowBuilder.remove(ruleBuilder.build());
-                break;
-            default:
-                log.warn("Unknown operation {}", objective.op());
-        }
-
-        flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                objective.context().ifPresent(context -> context.onSuccess(objective));
-            }
-
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                objective.context()
-                        .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
-            }
-        }));
-    }
-
-    @Override
-    public void forward(ForwardingObjective fwd) {
-
-        if (checkForMulticast(fwd)) {
-            processMulticastRule(fwd);
-            return;
-        }
-
-        if (checkForEAPOL(fwd)) {
-            log.warn("Discarding EAPOL flow which is not supported on this pipeline");
-            return;
-        }
-
-        TrafficTreatment treatment = fwd.treatment();
-
-        List<Instruction> instructions = treatment.allInstructions();
-
-        Optional<Instruction> vlanIntruction = instructions.stream()
-                .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
-                .filter(i -> ((L2ModificationInstruction) i).subtype() ==
-                        L2ModificationInstruction.L2SubType.VLAN_PUSH ||
-                        ((L2ModificationInstruction) i).subtype() ==
-                                L2ModificationInstruction.L2SubType.VLAN_POP)
-                .findAny();
-
-        if (vlanIntruction.isPresent()) {
-            L2ModificationInstruction vlanIns =
-                    (L2ModificationInstruction) vlanIntruction.get();
-
-            if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
-                installUpstreamRules(fwd);
-            } else if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
-                installDownstreamRules(fwd);
-            } else {
-                log.error("Unknown OLT operation: {}", fwd);
-                fail(fwd, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-
-            pass(fwd);
-        } else {
-            TrafficSelector selector = fwd.selector();
-
-            if (fwd.treatment() != null) {
-                // Deal with SPECIFIC and VERSATILE in the same manner.
-                FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
-                        .forDevice(deviceId)
-                        .withSelector(selector)
-                        .fromApp(fwd.appId())
-                        .withPriority(fwd.priority())
-                        .withTreatment(fwd.treatment());
-
-                if (fwd.permanent()) {
-                    ruleBuilder.makePermanent();
-                } else {
-                    ruleBuilder.makeTemporary(fwd.timeout());
-                }
-                installObjective(ruleBuilder, fwd);
-
-            } else {
-                log.error("No treatment error: {}", fwd);
-                fail(fwd, ObjectiveError.UNSUPPORTED);
-            }
-        }
-
-    }
-
-
-    @Override
-    public void next(NextObjective nextObjective) {
-        if (nextObjective.type() != NextObjective.Type.BROADCAST) {
-            log.error("OLT only supports broadcast groups.");
-            fail(nextObjective, ObjectiveError.BADPARAMS);
-        }
-
-        if (nextObjective.next().size() != 1) {
-            log.error("OLT only supports singleton broadcast groups.");
-            fail(nextObjective, ObjectiveError.BADPARAMS);
-        }
-
-        TrafficTreatment treatment = nextObjective.next().stream().findFirst().get();
-
-
-        GroupBucket bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
-        GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
-
-
-        pendingGroups.put(key, nextObjective);
-
-        switch (nextObjective.op()) {
-            case ADD:
-                GroupDescription groupDesc =
-                        new DefaultGroupDescription(deviceId,
-                                                    GroupDescription.Type.ALL,
-                                                    new GroupBuckets(Collections.singletonList(bucket)),
-                                                    key,
-                                                    null,
-                                                    nextObjective.appId());
-                groupService.addGroup(groupDesc);
-                break;
-            case REMOVE:
-                groupService.removeGroup(deviceId, key, nextObjective.appId());
-                break;
-            case ADD_TO_EXISTING:
-                groupService.addBucketsToGroup(deviceId, key,
-                                               new GroupBuckets(Collections.singletonList(bucket)),
-                                               key, nextObjective.appId());
-                break;
-            case REMOVE_FROM_EXISTING:
-                groupService.removeBucketsFromGroup(deviceId, key,
-                                                    new GroupBuckets(Collections.singletonList(bucket)),
-                                                    key, nextObjective.appId());
-                break;
-            default:
-                log.warn("Unknown next objective operation: {}", nextObjective.op());
-        }
-
-
-    }
-
-    private void processMulticastRule(ForwardingObjective fwd) {
-        if (fwd.nextId() == null) {
-            log.error("Multicast objective does not have a next id");
-            fail(fwd, ObjectiveError.BADPARAMS);
-        }
-
-        GroupKey key = getGroupForNextObjective(fwd.nextId());
-
-        if (key == null) {
-            log.error("Group for forwarding objective missing: {}", fwd);
-            fail(fwd, ObjectiveError.GROUPMISSING);
-        }
-
-        Group group = groupService.getGroup(deviceId, key);
-        TrafficTreatment treatment =
-                buildTreatment(Instructions.createGroup(group.id()));
-
-        FlowRule rule = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(0)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(fwd.selector())
-                .withTreatment(treatment)
-                .build();
-
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        switch (fwd.op()) {
-
-            case ADD:
-                builder.add(rule);
-                break;
-            case REMOVE:
-                builder.remove(rule);
-                break;
-            case ADD_TO_EXISTING:
-            case REMOVE_FROM_EXISTING:
-                break;
-            default:
-                log.warn("Unknown forwarding operation: {}", fwd.op());
-        }
-
-        applyFlowRules(builder, fwd);
-
-    }
-
-    private boolean checkForMulticast(ForwardingObjective fwd) {
-
-        IPCriterion ip = (IPCriterion) filterForCriterion(fwd.selector().criteria(),
-                                                          Criterion.Type.IPV4_DST);
-
-        if (ip == null) {
-            return false;
-        }
-
-        return ip.ip().isMulticast();
-
-    }
-
-    private boolean checkForEAPOL(ForwardingObjective fwd) {
-        EthTypeCriterion ethType = (EthTypeCriterion)
-                filterForCriterion(fwd.selector().criteria(), Criterion.Type.ETH_TYPE);
-
-        return ethType != null && ethType.ethType().equals(EthType.EtherType.EAPOL.ethType());
-    }
-    private GroupKey getGroupForNextObjective(Integer nextId) {
-        NextGroup next = flowObjectiveStore.getNextGroup(nextId);
-        return appKryo.deserialize(next.data());
-
-    }
-
-    private void installDownstreamRules(ForwardingObjective fwd) {
-        List<Pair<Instruction, Instruction>> vlanOps =
-                vlanOps(fwd,
-                        L2ModificationInstruction.L2SubType.VLAN_POP);
-
-        if (vlanOps == null) {
-            return;
-        }
-
-        Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, "downstream");
-
-        if (output == null) {
-            return;
-        }
-
-        Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0);
-
-        TrafficSelector selector = fwd.selector();
-
-        Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
-        Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
-        Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
-        Criterion bullshit = Criteria.matchMetadata(output.port().toLong());
-
-        if (outerVlan == null || innerVlan == null || inport == null) {
-            log.error("Forwarding objective is underspecified: {}", fwd);
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        Criterion innerVid = Criteria.matchVlanId(((VlanIdCriterion) innerVlan).vlanId());
-
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(buildSelector(inport, outerVlan, bullshit))
-                .withTreatment(buildTreatment(popAndRewrite.getLeft(),
-                        Instructions.transition(QQ_TABLE)));
-
-        FlowRule.Builder inner = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(buildSelector(inport, innerVid))
-                .withTreatment(buildTreatment(popAndRewrite.getLeft(),
-                                              output));
-
-        applyRules(fwd, inner, outer);
-
-    }
-
-    private boolean hasUntaggedVlanTag(TrafficSelector selector) {
-        Iterator<Criterion> iter = selector.criteria().iterator();
-
-        while (iter.hasNext()) {
-            Criterion criterion = iter.next();
-            if (criterion.type() == Criterion.Type.VLAN_VID &&
-                    ((VlanIdCriterion) criterion).vlanId().toShort() == VlanId.UNTAGGED) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private void installUpstreamRules(ForwardingObjective fwd) {
-        List<Pair<Instruction, Instruction>> vlanOps =
-                vlanOps(fwd,
-                        L2ModificationInstruction.L2SubType.VLAN_PUSH);
-        FlowRule.Builder inner;
-
-        if (vlanOps == null) {
-            return;
-        }
-
-        Instruction output = fetchOutput(fwd, "upstream");
-
-        if (output == null) {
-            return;
-        }
-
-        Pair<Instruction, Instruction> innerPair = vlanOps.remove(0);
-
-        Pair<Instruction, Instruction> outerPair = vlanOps.remove(0);
-
-
-        if (hasUntaggedVlanTag(fwd.selector())) {
-            inner = DefaultFlowRule.builder()
-                    .fromApp(fwd.appId())
-                    .forDevice(deviceId)
-                    .makePermanent()
-                    .withPriority(fwd.priority())
-                    .withSelector(fwd.selector())
-                    .withTreatment(buildTreatment(innerPair.getLeft(),
-                            innerPair.getRight(),
-                            Instructions.transition(QQ_TABLE)));
-        } else {
-            inner = DefaultFlowRule.builder()
-                    .fromApp(fwd.appId())
-                    .forDevice(deviceId)
-                    .makePermanent()
-                    .withPriority(fwd.priority())
-                    .withSelector(fwd.selector())
-                    .withTreatment(buildTreatment(
-                            innerPair.getRight(),
-                            Instructions.transition(QQ_TABLE)));
-        }
-
-
-        PortCriterion inPort = (PortCriterion)
-                fwd.selector().getCriterion(Criterion.Type.IN_PORT);
-
-        VlanId cVlanId = ((L2ModificationInstruction.ModVlanIdInstruction)
-                innerPair.getRight()).vlanId();
-
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(buildSelector(inPort,
-                                            Criteria.matchVlanId(cVlanId)))
-                .withTreatment(buildTreatment(outerPair.getLeft(),
-                                              outerPair.getRight(),
-                                              output));
-
-        applyRules(fwd, inner, outer);
-
-    }
-
-    private Instruction fetchOutput(ForwardingObjective fwd, String direction) {
-        Instruction output = fwd.treatment().allInstructions().stream()
-                .filter(i -> i.type() == Instruction.Type.OUTPUT)
-                .findFirst().orElse(null);
-
-        if (output == null) {
-            log.error("OLT {} rule has no output", direction);
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return null;
-        }
-        return output;
-    }
-
-    private List<Pair<Instruction, Instruction>> vlanOps(ForwardingObjective fwd,
-                                                         L2ModificationInstruction.L2SubType type) {
-
-        List<Pair<Instruction, Instruction>> vlanOps = findVlanOps(
-                fwd.treatment().allInstructions(), type);
-
-        if (vlanOps == null) {
-            String direction = type == L2ModificationInstruction.L2SubType.VLAN_POP
-                    ? "downstream" : "upstream";
-            log.error("Missing vlan operations in {} forwarding: {}", direction, fwd);
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return null;
-        }
-        return vlanOps;
-    }
-
-
-    private List<Pair<Instruction, Instruction>> findVlanOps(List<Instruction> instructions,
-                                                             L2ModificationInstruction.L2SubType type) {
-
-        List<Instruction> vlanPushs = findL2Instructions(
-                type,
-                instructions);
-        List<Instruction> vlanSets = findL2Instructions(
-                L2ModificationInstruction.L2SubType.VLAN_ID,
-                instructions);
-
-        if (vlanPushs.size() != vlanSets.size()) {
-            return null;
-        }
-
-        List<Pair<Instruction, Instruction>> pairs = Lists.newArrayList();
-
-        for (int i = 0; i < vlanPushs.size(); i++) {
-            pairs.add(new ImmutablePair<>(vlanPushs.get(i), vlanSets.get(i)));
-        }
-        return pairs;
-    }
-
-    private List<Instruction> findL2Instructions(L2ModificationInstruction.L2SubType subType,
-                                                 List<Instruction> actions) {
-        return actions.stream()
-                .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
-                .filter(i -> ((L2ModificationInstruction) i).subtype() == subType)
-                .collect(Collectors.toList());
-    }
-
-    private void provisionEapol(FilteringObjective filter,
-                                EthTypeCriterion ethType,
-                                Instructions.OutputInstruction output) {
-
-        TrafficSelector selector = buildSelector(filter.key(), ethType);
-        TrafficTreatment treatment = buildTreatment(output);
-        buildAndApplyRule(filter, selector, treatment, EAPOL_FLOW_PRIORITY);
-
-    }
-
-    private void provisionIgmp(FilteringObjective filter, EthTypeCriterion ethType,
-                               IPProtocolCriterion ipProto,
-                               Instructions.OutputInstruction output) {
-        TrafficSelector selector = buildSelector(filter.key(), ethType, ipProto);
-        TrafficTreatment treatment = buildTreatment(output);
-        buildAndApplyRule(filter, selector, treatment);
-    }
-
-    private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
-                                   TrafficTreatment treatment) {
-        buildAndApplyRule(filter, selector, treatment, filter.priority());
-    }
-
-    private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
-                                   TrafficTreatment treatment, int priority) {
-        FlowRule rule = DefaultFlowRule.builder()
-                .fromApp(filter.appId())
-                .forDevice(deviceId)
-                .forTable(0)
-                .makePermanent()
-                .withSelector(selector)
-                .withTreatment(treatment)
-                .withPriority(priority)
-                .build();
-
-        FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
-
-        switch (filter.type()) {
-            case PERMIT:
-                opsBuilder.add(rule);
-                break;
-            case DENY:
-                opsBuilder.remove(rule);
-                break;
-            default:
-                log.warn("Unknown filter type : {}", filter.type());
-                fail(filter, ObjectiveError.UNSUPPORTED);
-        }
-
-        applyFlowRules(opsBuilder, filter);
-    }
-
-    private void applyRules(ForwardingObjective fwd,
-                            FlowRule.Builder inner, FlowRule.Builder outer) {
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        switch (fwd.op()) {
-            case ADD:
-                builder.add(inner.build()).add(outer.build());
-                break;
-            case REMOVE:
-                builder.remove(inner.build()).remove(outer.build());
-                break;
-            case ADD_TO_EXISTING:
-                break;
-            case REMOVE_FROM_EXISTING:
-                break;
-            default:
-                log.warn("Unknown forwarding operation: {}", fwd.op());
-        }
-
-        applyFlowRules(builder, fwd);
-    }
-
-    private void applyFlowRules(FlowRuleOperations.Builder builder,
-                                Objective objective) {
-        flowRuleService.apply(builder.build(new FlowRuleOperationsContext() {
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                pass(objective);
-            }
-
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                fail(objective, ObjectiveError.FLOWINSTALLATIONFAILED);
-            }
-        }));
-    }
-
-    private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
-        return criteria.stream()
-                .filter(c -> c.type().equals(type))
-                .limit(1)
-                .findFirst().orElse(null);
-    }
-
-    private TrafficSelector buildSelector(Criterion... criteria) {
-
-
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
-        for (Criterion c : criteria) {
-            sBuilder.add(c);
-        }
-
-        return sBuilder.build();
-    }
-
-    private TrafficTreatment buildTreatment(Instruction... instructions) {
-
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
-        for (Instruction i : instructions) {
-            tBuilder.add(i);
-        }
-
-        return tBuilder.build();
-    }
-
-
-    private void fail(Objective obj, ObjectiveError error) {
-        obj.context().ifPresent(context -> context.onError(obj, error));
-    }
-
-    private void pass(Objective obj) {
-        obj.context().ifPresent(context -> context.onSuccess(obj));
-    }
-
-
-    private class InnerGroupListener implements GroupListener {
-        @Override
-        public void event(GroupEvent event) {
-            if (event.type() == GroupEvent.Type.GROUP_ADDED || event.type() == GroupEvent.Type.GROUP_UPDATED) {
-                GroupKey key = event.subject().appCookie();
-
-                NextObjective obj = pendingGroups.getIfPresent(key);
-                if (obj != null) {
-                    flowObjectiveStore.putNextGroup(obj.id(), new OLTPipelineGroup(key));
-                    pass(obj);
-                    pendingGroups.invalidate(key);
-                }
-            }
-        }
-    }
-
-    private static class OLTPipelineGroup implements NextGroup {
-
-        private final GroupKey key;
-
-        public OLTPipelineGroup(GroupKey key) {
-            this.key = key;
-        }
-
-        public GroupKey key() {
-            return key;
-        }
-
-        @Override
-        public byte[] data() {
-            return appKryo.serialize(key);
-        }
-
-    }
-
-    @Override
-    public List<String> getNextMappings(NextGroup nextGroup) {
-        // TODO Implementation deferred to vendor
-        return null;
-    }
-}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
deleted file mode 100644
index 6790e58..0000000
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
+++ /dev/null
@@ -1,1287 +0,0 @@
-/*
- * 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.driver.pipeline;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onlab.util.AbstractAccumulator;
-import org.onlab.util.Accumulator;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.NextGroup;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.driver.Driver;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.IPProtocolCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.UdpPortCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveStore;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.DefaultGroupDescription;
-import org.onosproject.net.group.DefaultGroupKey;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.group.GroupDescription;
-import org.onosproject.net.group.GroupEvent;
-import org.onosproject.net.group.GroupKey;
-import org.onosproject.net.group.GroupListener;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.StorageService;
-import org.slf4j.Logger;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.Timer;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onosproject.core.CoreService.CORE_APP_NAME;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-
-public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
-    private static final Integer QQ_TABLE = 1;
-    private static final int NO_ACTION_PRIORITY = 500;
-    private static final String DOWNSTREAM = "downstream";
-    private static final String UPSTREAM = "upstream";
-    private final Logger log = getLogger(getClass());
-
-    private ServiceDirectory serviceDirectory;
-    private FlowRuleService flowRuleService;
-    private GroupService groupService;
-    private CoreService coreService;
-    private StorageService storageService;
-
-    private DeviceId deviceId;
-    private ApplicationId appId;
-
-
-    protected FlowObjectiveStore flowObjectiveStore;
-
-    private Cache<GroupKey, NextObjective> pendingGroups;
-
-    protected static KryoNamespace appKryo = new KryoNamespace.Builder()
-            .register(KryoNamespaces.API)
-            .register(GroupKey.class)
-            .register(DefaultGroupKey.class)
-            .register(OLTPipelineGroup.class)
-            .build("OltPipeline");
-
-    private static final Timer TIMER = new Timer("filterobj-batching");
-    private Accumulator<Pair<FilteringObjective, FlowRule>> accumulator;
-
-    // accumulator executor service
-    private ScheduledExecutorService accumulatorExecutorService
-            = newSingleThreadScheduledExecutor(groupedThreads("OltPipeliner", "acc-%d", log));
-
-    @Override
-    public void init(DeviceId deviceId, PipelinerContext context) {
-        log.debug("Initiate OLT pipeline");
-        this.serviceDirectory = context.directory();
-        this.deviceId = deviceId;
-
-        flowRuleService = serviceDirectory.get(FlowRuleService.class);
-        coreService = serviceDirectory.get(CoreService.class);
-        groupService = serviceDirectory.get(GroupService.class);
-        flowObjectiveStore = context.store();
-        storageService = serviceDirectory.get(StorageService.class);
-
-        appId = coreService.registerApplication(
-                "org.onosproject.driver.OLTPipeline");
-
-        // Init the accumulator, if enabled
-        if (isAccumulatorEnabled()) {
-            log.debug("Building accumulator with maxObjs {}, batchMs {}, idleMs {}",
-                      context.accumulatorMaxObjectives(), context.accumulatorMaxBatchMillis(),
-                      context.accumulatorMaxIdleMillis());
-            accumulator = new ObjectiveAccumulator(context.accumulatorMaxObjectives(),
-                                                             context.accumulatorMaxBatchMillis(),
-                                                             context.accumulatorMaxIdleMillis());
-        }
-
-
-        pendingGroups = CacheBuilder.newBuilder()
-                .expireAfterWrite(20, TimeUnit.SECONDS)
-                .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
-                    if (notification.getCause() == RemovalCause.EXPIRED) {
-                        fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
-                    }
-                }).build();
-
-        groupService.addListener(new InnerGroupListener());
-
-    }
-
-    public boolean isAccumulatorEnabled() {
-        Driver driver = super.data().driver();
-        // we cannot determine the property
-        if (driver == null) {
-            return false;
-        }
-        return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
-    }
-
-    @Override
-    public void filter(FilteringObjective filter) {
-        Instructions.OutputInstruction output;
-
-        if (filter.meta() != null && !filter.meta().immediate().isEmpty()) {
-            output = (Instructions.OutputInstruction) filter.meta().immediate().stream()
-                    .filter(t -> t.type().equals(Instruction.Type.OUTPUT))
-                    .limit(1)
-                    .findFirst().get();
-
-            if (output == null || !output.port().equals(PortNumber.CONTROLLER)) {
-                log.warn("OLT can only filter packet to controller");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-        } else {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        if (filter.key().type() != Criterion.Type.IN_PORT) {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        EthTypeCriterion ethType = (EthTypeCriterion)
-                filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE);
-
-        if (ethType == null) {
-            fail(filter, ObjectiveError.BADPARAMS);
-            return;
-        }
-        Optional<Instruction> vlanId = filter.meta().immediate().stream()
-                .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
-                        && ((L2ModificationInstruction) t).subtype()
-                        .equals(L2ModificationInstruction.L2SubType.VLAN_ID))
-                .limit(1)
-                .findFirst();
-
-        Optional<Instruction> vlanPcp = filter.meta().immediate().stream()
-                .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
-                        && ((L2ModificationInstruction) t).subtype()
-                        .equals(L2ModificationInstruction.L2SubType.VLAN_PCP))
-                .limit(1)
-                .findFirst();
-
-        Optional<Instruction> vlanPush = filter.meta().immediate().stream()
-                .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
-                        && ((L2ModificationInstruction) t).subtype()
-                        .equals(L2ModificationInstruction.L2SubType.VLAN_PUSH))
-                .limit(1)
-                .findFirst();
-
-        if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) {
-
-            if (vlanId.isEmpty() || vlanPush.isEmpty()) {
-                log.warn("Missing EAPOL vlan or vlanPush");
-                fail(filter, ObjectiveError.BADPARAMS);
-                return;
-            }
-            provisionEthTypeBasedFilter(filter, ethType, output,
-                                        (L2ModificationInstruction) vlanId.get(),
-                                        (L2ModificationInstruction) vlanPush.get());
-        } else if (ethType.ethType().equals(EthType.EtherType.PPPoED.ethType()))  {
-            provisionPPPoED(filter, ethType, vlanId.orElse(null), vlanPcp.orElse(null), output);
-        } else if (ethType.ethType().equals(EthType.EtherType.LLDP.ethType())) {
-            provisionEthTypeBasedFilter(filter, ethType, output, null, null);
-        } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) {
-            IPProtocolCriterion ipProto = (IPProtocolCriterion)
-                    filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
-            if (ipProto == null) {
-                log.warn("OLT can only filter IGMP and DHCP");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-            if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) {
-                provisionIgmp(filter, ethType, ipProto, output,
-                              vlanId.orElse(null),
-                              vlanPcp.orElse(null));
-            } else if (ipProto.protocol() == IPv4.PROTOCOL_UDP) {
-                UdpPortCriterion udpSrcPort = (UdpPortCriterion)
-                        filterForCriterion(filter.conditions(), Criterion.Type.UDP_SRC);
-
-                UdpPortCriterion udpDstPort = (UdpPortCriterion)
-                        filterForCriterion(filter.conditions(), Criterion.Type.UDP_DST);
-
-                if ((udpSrcPort.udpPort().toInt() == 67 && udpDstPort.udpPort().toInt() == 68) ||
-                    (udpSrcPort.udpPort().toInt() == 68 && udpDstPort.udpPort().toInt() == 67)) {
-                    provisionDhcp(filter, ethType, ipProto, udpSrcPort, udpDstPort, vlanId.orElse(null),
-                                  vlanPcp.orElse(null), output);
-                } else {
-                    log.warn("Filtering rule with unsupported UDP src {} or dst {} port", udpSrcPort, udpDstPort);
-                    fail(filter, ObjectiveError.UNSUPPORTED);
-                }
-            } else {
-                log.warn("Currently supporting only IGMP and DHCP filters for IPv4 packets");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-            }
-        } else if (ethType.ethType().equals(EthType.EtherType.IPV6.ethType())) {
-            IPProtocolCriterion ipProto = (IPProtocolCriterion)
-                    filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
-            if (ipProto == null) {
-                log.warn("OLT can only filter DHCP");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-            if (ipProto.protocol() == IPv6.PROTOCOL_UDP) {
-                UdpPortCriterion udpSrcPort = (UdpPortCriterion)
-                        filterForCriterion(filter.conditions(), Criterion.Type.UDP_SRC);
-
-                UdpPortCriterion udpDstPort = (UdpPortCriterion)
-                        filterForCriterion(filter.conditions(), Criterion.Type.UDP_DST);
-
-                if ((udpSrcPort.udpPort().toInt() == 546 && udpDstPort.udpPort().toInt() == 547) ||
-                    (udpSrcPort.udpPort().toInt() == 547 && udpDstPort.udpPort().toInt() == 546)) {
-                    provisionDhcp(filter, ethType, ipProto, udpSrcPort, udpDstPort, vlanId.orElse(null),
-                                  vlanPcp.orElse(null), output);
-                } else {
-                    log.warn("Filtering rule with unsupported UDP src {} or dst {} port", udpSrcPort, udpDstPort);
-                    fail(filter, ObjectiveError.UNSUPPORTED);
-                }
-            } else {
-                log.warn("Currently supporting only DHCP filters for IPv6 packets");
-                fail(filter, ObjectiveError.UNSUPPORTED);
-            }
-        } else {
-            log.warn("\nOnly the following are Supported in OLT for filter ->\n"
-                    + "ETH TYPE : EAPOL, LLDP and IPV4\n"
-                    + "IPV4 TYPE: IGMP and UDP (for DHCP)"
-                    + "IPV6 TYPE: UDP (for DHCP)");
-            fail(filter, ObjectiveError.UNSUPPORTED);
-        }
-
-    }
-
-
-    @Override
-    public void forward(ForwardingObjective fwd) {
-        log.debug("Installing forwarding objective {}", fwd);
-        if (checkForMulticast(fwd)) {
-            processMulticastRule(fwd);
-            return;
-        }
-
-        TrafficTreatment treatment = fwd.treatment();
-
-        List<Instruction> instructions = treatment.allInstructions();
-
-        Optional<Instruction> vlanInstruction = instructions.stream()
-                .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
-                .filter(i -> ((L2ModificationInstruction) i).subtype() ==
-                        L2ModificationInstruction.L2SubType.VLAN_PUSH ||
-                        ((L2ModificationInstruction) i).subtype() ==
-                                L2ModificationInstruction.L2SubType.VLAN_POP)
-                .findAny();
-
-
-        if (!vlanInstruction.isPresent()) {
-            installNoModificationRules(fwd);
-        } else {
-            L2ModificationInstruction vlanIns =
-                    (L2ModificationInstruction) vlanInstruction.get();
-            if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
-                installUpstreamRules(fwd);
-            } else if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
-                installDownstreamRules(fwd);
-            } else {
-                log.error("Unknown OLT operation: {}", fwd);
-                fail(fwd, ObjectiveError.UNSUPPORTED);
-                return;
-            }
-        }
-
-        pass(fwd);
-
-    }
-
-
-    @Override
-    public void next(NextObjective nextObjective) {
-        if (nextObjective.type() != NextObjective.Type.BROADCAST) {
-            log.error("OLT only supports broadcast groups.");
-            fail(nextObjective, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        if (nextObjective.next().size() != 1 && !nextObjective.op().equals(Objective.Operation.REMOVE)) {
-            log.error("OLT only supports singleton broadcast groups.");
-            fail(nextObjective, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        Optional<TrafficTreatment> treatmentOpt = nextObjective.next().stream().findFirst();
-        if (treatmentOpt.isEmpty() && !nextObjective.op().equals(Objective.Operation.REMOVE)) {
-            log.error("Next objective {} does not have a treatment", nextObjective);
-            fail(nextObjective, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
-
-        pendingGroups.put(key, nextObjective);
-        log.trace("NextObjective Operation {}", nextObjective.op());
-        switch (nextObjective.op()) {
-            case ADD:
-                GroupDescription groupDesc =
-                        new DefaultGroupDescription(deviceId,
-                                                    GroupDescription.Type.ALL,
-                                                    new GroupBuckets(
-                                                            Collections.singletonList(
-                                                                buildBucket(treatmentOpt.get()))),
-                                                    key,
-                                                    null,
-                                                    nextObjective.appId());
-                groupService.addGroup(groupDesc);
-                break;
-            case REMOVE:
-                groupService.removeGroup(deviceId, key, nextObjective.appId());
-                break;
-            case ADD_TO_EXISTING:
-                groupService.addBucketsToGroup(deviceId, key,
-                                               new GroupBuckets(
-                                                       Collections.singletonList(
-                                                               buildBucket(treatmentOpt.get()))),
-                                               key, nextObjective.appId());
-                break;
-            case REMOVE_FROM_EXISTING:
-                groupService.removeBucketsFromGroup(deviceId, key,
-                                                    new GroupBuckets(
-                                                            Collections.singletonList(
-                                                                buildBucket(treatmentOpt.get()))),
-                                                    key, nextObjective.appId());
-                break;
-            default:
-                log.warn("Unknown next objective operation: {}", nextObjective.op());
-        }
-
-
-    }
-
-    private GroupBucket buildBucket(TrafficTreatment treatment) {
-        return DefaultGroupBucket.createAllGroupBucket(treatment);
-    }
-
-    private void processMulticastRule(ForwardingObjective fwd) {
-        if (fwd.nextId() == null) {
-            log.error("Multicast objective does not have a next id");
-            fail(fwd, ObjectiveError.BADPARAMS);
-        }
-
-        GroupKey key = getGroupForNextObjective(fwd.nextId());
-
-        if (key == null) {
-            log.error("Group for forwarding objective missing: {}", fwd);
-            fail(fwd, ObjectiveError.GROUPMISSING);
-        }
-
-        Group group = groupService.getGroup(deviceId, key);
-        TrafficTreatment treatment =
-                buildTreatment(Instructions.createGroup(group.id()));
-
-        TrafficSelector.Builder selectorBuilder = buildIpv4SelectorForMulticast(fwd);
-
-        FlowRule rule = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(0)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(selectorBuilder.build())
-                .withTreatment(treatment)
-                .build();
-
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        switch (fwd.op()) {
-
-            case ADD:
-                builder.add(rule);
-                break;
-            case REMOVE:
-                builder.remove(rule);
-                break;
-            case ADD_TO_EXISTING:
-            case REMOVE_FROM_EXISTING:
-                break;
-            default:
-                log.warn("Unknown forwarding operation: {}", fwd.op());
-        }
-
-        applyFlowRules(ImmutableList.of(fwd), builder);
-
-
-    }
-
-    private TrafficSelector.Builder buildIpv4SelectorForMulticast(ForwardingObjective fwd) {
-        TrafficSelector.Builder builderToUpdate = DefaultTrafficSelector.builder();
-
-        Optional<Criterion> vlanIdCriterion = readFromSelector(fwd.meta(), Criterion.Type.VLAN_VID);
-        if (vlanIdCriterion.isPresent()) {
-            VlanId assignedVlan = ((VlanIdCriterion) vlanIdCriterion.get()).vlanId();
-            builderToUpdate.matchVlanId(assignedVlan);
-        }
-
-        Optional<Criterion> innerVlanIdCriterion = readFromSelector(fwd.meta(), Criterion.Type.INNER_VLAN_VID);
-        if (innerVlanIdCriterion.isPresent()) {
-            VlanId assignedInnerVlan = ((VlanIdCriterion) innerVlanIdCriterion.get()).vlanId();
-            builderToUpdate.matchMetadata(assignedInnerVlan.toShort());
-        }
-
-        Optional<Criterion> ethTypeCriterion = readFromSelector(fwd.selector(), Criterion.Type.ETH_TYPE);
-        if (ethTypeCriterion.isPresent()) {
-            EthType ethType = ((EthTypeCriterion) ethTypeCriterion.get()).ethType();
-            builderToUpdate.matchEthType(ethType.toShort());
-        }
-
-        Optional<Criterion> ipv4DstCriterion = readFromSelector(fwd.selector(), Criterion.Type.IPV4_DST);
-        if (ipv4DstCriterion.isPresent()) {
-            IpPrefix ipv4Dst = ((IPCriterion) ipv4DstCriterion.get()).ip();
-            builderToUpdate.matchIPDst(ipv4Dst);
-        }
-
-        return builderToUpdate;
-    }
-
-    static Optional<Criterion> readFromSelector(TrafficSelector selector, Criterion.Type type) {
-        if (selector == null) {
-            return Optional.empty();
-        }
-        Criterion criterion = selector.getCriterion(type);
-        return (criterion == null)
-                ? Optional.empty() : Optional.of(criterion);
-    }
-
-    private boolean checkForMulticast(ForwardingObjective fwd) {
-
-        IPCriterion ip = (IPCriterion) filterForCriterion(fwd.selector().criteria(),
-                                                          Criterion.Type.IPV4_DST);
-
-        if (ip == null) {
-            return false;
-        }
-
-        return ip.ip().isMulticast();
-
-    }
-
-    private GroupKey getGroupForNextObjective(Integer nextId) {
-        NextGroup next = flowObjectiveStore.getNextGroup(nextId);
-        return appKryo.deserialize(next.data());
-
-    }
-
-    private void installNoModificationRules(ForwardingObjective fwd) {
-        Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, DOWNSTREAM);
-        Instructions.MetadataInstruction writeMetadata = fetchWriteMetadata(fwd);
-        Instructions.MeterInstruction meter = (Instructions.MeterInstruction) fetchMeter(fwd);
-
-        TrafficSelector selector = fwd.selector();
-
-        Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
-        Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
-        Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
-
-        if (inport == null || output == null || innerVlan == null || outerVlan == null) {
-            // Avoid logging a non-error from lldp, bbdp and eapol core flows.
-            if (!fwd.appId().name().equals(CORE_APP_NAME)) {
-                log.error("Forwarding objective is underspecified: {}", fwd);
-            } else {
-                log.debug("Not installing unsupported core generated flow {}", fwd);
-            }
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(buildSelector(inport, outerVlan))
-                .withTreatment(buildTreatment(output, writeMetadata, meter));
-
-        applyRules(fwd, outer);
-    }
-
-    private void installDownstreamRules(ForwardingObjective fwd) {
-        Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, DOWNSTREAM);
-
-        if (output == null) {
-            return;
-        }
-
-        TrafficSelector selector = fwd.selector();
-
-        Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
-        Criterion outerPbit = selector.getCriterion(Criterion.Type.VLAN_PCP);
-        Criterion innerVlanCriterion = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
-        Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
-        Criterion dstMac = selector.getCriterion(Criterion.Type.ETH_DST);
-
-        if (outerVlan == null || innerVlanCriterion == null || inport == null) {
-            // Avoid logging a non-error from lldp, bbdp and eapol core flows.
-            if (!fwd.appId().name().equals(CORE_APP_NAME)) {
-                log.error("Forwarding objective is underspecified: {}", fwd);
-            } else {
-                log.debug("Not installing unsupported core generated flow {}", fwd);
-            }
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return;
-        }
-
-        VlanId innerVlan = ((VlanIdCriterion) innerVlanCriterion).vlanId();
-        Criterion innerVid = Criteria.matchVlanId(innerVlan);
-
-        // In the case where the C-tag is the same for all the subscribers,
-        // we add a metadata with the outport in the selector to make the flow unique
-        Criterion innerSelectorMeta = Criteria.matchMetadata(output.port().toLong());
-
-        if (innerVlan.toShort() == VlanId.ANY_VALUE) {
-            TrafficSelector outerSelector = buildSelector(inport, outerVlan, outerPbit, dstMac);
-            installDownstreamRulesForAnyVlan(fwd, output, outerSelector, buildSelector(inport,
-                    Criteria.matchVlanId(VlanId.ANY), innerSelectorMeta));
-        } else {
-            // Required to differentiate the same match flows
-            // Please note that S tag and S p bit values will be same for the same service - so conflict flows!
-            // Metadata match criteria solves the conflict issue - but not used by the voltha
-            // Maybe - find a better way to solve the above problem
-            Criterion metadata = Criteria.matchMetadata(innerVlan.toShort());
-            TrafficSelector outerSelector = buildSelector(inport, metadata, outerVlan, outerPbit, dstMac);
-            installDownstreamRulesForVlans(fwd, output, outerSelector, buildSelector(inport, innerVid,
-                    innerSelectorMeta));
-        }
-    }
-
-    private void installDownstreamRulesForVlans(ForwardingObjective fwd, Instruction output,
-                                                TrafficSelector outerSelector, TrafficSelector innerSelector) {
-
-        List<Pair<Instruction, Instruction>> vlanOps =
-                vlanOps(fwd,
-                        L2ModificationInstruction.L2SubType.VLAN_POP);
-
-        if (vlanOps == null || vlanOps.isEmpty()) {
-            return;
-        }
-
-        Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0);
-
-        TrafficTreatment innerTreatment;
-        VlanId setVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) popAndRewrite.getRight()).vlanId();
-        if (VlanId.NONE.equals(setVlanId)) {
-            innerTreatment = (buildTreatment(popAndRewrite.getLeft(), fetchMeter(fwd),
-                    writeMetadataIncludingOnlyTp(fwd), output));
-        } else {
-            innerTreatment = (buildTreatment(popAndRewrite.getRight(),
-                    fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd), output));
-        }
-
-        List<Instruction> setVlanPcps = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
-                fwd.treatment().allInstructions());
-
-        Instruction innerPbitSet = null;
-
-        if (setVlanPcps != null && !setVlanPcps.isEmpty()) {
-            innerPbitSet = setVlanPcps.get(0);
-        }
-
-        VlanId remarkInnerVlan = null;
-        Optional<Criterion> vlanIdCriterion = readFromSelector(innerSelector, Criterion.Type.VLAN_VID);
-        if (vlanIdCriterion.isPresent()) {
-            remarkInnerVlan = ((VlanIdCriterion) vlanIdCriterion.get()).vlanId();
-        }
-
-        Instruction modVlanId = null;
-        if (innerPbitSet != null) {
-            modVlanId = Instructions.modVlanId(remarkInnerVlan);
-        }
-
-        //match: in port (nni), s-tag
-        //action: pop vlan (s-tag), write metadata, go to table 1, meter
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(outerSelector)
-                .withTreatment(buildTreatment(popAndRewrite.getLeft(), modVlanId,
-                        innerPbitSet, fetchMeter(fwd), fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE)));
-
-        //match: in port (nni), c-tag
-        //action: immediate: write metadata and pop, meter, output
-        FlowRule.Builder inner = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(innerSelector)
-                .withTreatment(innerTreatment);
-        applyRules(fwd, inner, outer);
-    }
-
-    private void installDownstreamRulesForAnyVlan(ForwardingObjective fwd, Instruction output,
-                                                  TrafficSelector outerSelector, TrafficSelector innerSelector) {
-
-        //match: in port (nni), s-tag
-        //action: immediate: write metadata, pop vlan, meter and go to table 1
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(outerSelector)
-                .withTreatment(buildTreatment(Instructions.popVlan(), fetchMeter(fwd),
-                        fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE)));
-
-        //match: in port (nni) and s-tag
-        //action: immediate : write metadata, meter and output
-        FlowRule.Builder inner = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(innerSelector)
-                .withTreatment(buildTreatment(fetchMeter(fwd),
-                        writeMetadataIncludingOnlyTp(fwd), output));
-
-        applyRules(fwd, inner, outer);
-    }
-
-    private void installUpstreamRules(ForwardingObjective fwd) {
-        List<Pair<Instruction, Instruction>> vlanOps =
-                vlanOps(fwd,
-                        L2ModificationInstruction.L2SubType.VLAN_PUSH);
-
-        if (vlanOps == null || vlanOps.isEmpty()) {
-            return;
-        }
-
-        Instruction output = fetchOutput(fwd, UPSTREAM);
-
-        if (output == null) {
-            return;
-        }
-
-        Pair<Instruction, Instruction> outerPair = vlanOps.remove(0);
-
-        boolean noneValueVlanStatus = checkNoneVlanCriteria(fwd);
-        boolean anyValueVlanStatus = checkAnyVlanMatchCriteria(fwd);
-
-        if (anyValueVlanStatus) {
-            installUpstreamRulesForAnyVlan(fwd, output, outerPair);
-        } else {
-            Pair<Instruction, Instruction> innerPair = outerPair;
-            outerPair = vlanOps.remove(0);
-            installUpstreamRulesForVlans(fwd, output, innerPair, outerPair, noneValueVlanStatus);
-        }
-    }
-
-    private void installUpstreamRulesForVlans(ForwardingObjective fwd, Instruction output,
-                                              Pair<Instruction, Instruction> innerPair,
-                                              Pair<Instruction, Instruction> outerPair, Boolean noneValueVlanStatus) {
-
-        List<Instruction> setVlanPcps = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
-                fwd.treatment().allInstructions());
-
-        Instruction innerPbitSet = null;
-        Instruction outerPbitSet = null;
-
-        if (setVlanPcps != null && !setVlanPcps.isEmpty()) {
-            innerPbitSet = setVlanPcps.get(0);
-            outerPbitSet = setVlanPcps.get(1);
-        }
-
-        TrafficTreatment innerTreatment;
-        if (noneValueVlanStatus) {
-            innerTreatment = buildTreatment(innerPair.getLeft(), innerPair.getRight(), fetchMeter(fwd),
-                    fetchWriteMetadata(fwd), innerPbitSet,
-                    Instructions.transition(QQ_TABLE));
-        } else {
-            innerTreatment = buildTreatment(innerPair.getRight(), fetchMeter(fwd), fetchWriteMetadata(fwd),
-                    innerPbitSet, Instructions.transition(QQ_TABLE));
-        }
-
-        //match: in port, vlanId (0 or None)
-        //action:
-        //if vlanId None, push & set c-tag go to table 1
-        //if vlanId 0 or any specific vlan, set c-tag, write metadata, meter and go to table 1
-        FlowRule.Builder inner = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(fwd.selector())
-                .withTreatment(innerTreatment);
-
-        PortCriterion inPort = (PortCriterion)
-                fwd.selector().getCriterion(Criterion.Type.IN_PORT);
-
-        VlanId cVlanId = ((L2ModificationInstruction.ModVlanIdInstruction)
-                innerPair.getRight()).vlanId();
-
-        //match: in port, c-tag
-        //action: immediate: push s-tag, write metadata, meter and output
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withTreatment(buildTreatment(outerPair.getLeft(), outerPair.getRight(),
-                        fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd),
-                        outerPbitSet, output));
-
-        if (innerPbitSet != null) {
-            byte innerPbit = ((L2ModificationInstruction.ModVlanPcpInstruction)
-                    innerPbitSet).vlanPcp();
-            outer.withSelector(buildSelector(inPort, Criteria.matchVlanId(cVlanId), Criteria.matchVlanPcp(innerPbit)));
-        } else {
-            outer.withSelector(buildSelector(inPort, Criteria.matchVlanId(cVlanId)));
-        }
-
-        applyRules(fwd, inner, outer);
-    }
-
-    private void installUpstreamRulesForAnyVlan(ForwardingObjective fwd, Instruction output,
-                                                Pair<Instruction, Instruction> outerPair) {
-
-        log.debug("Installing upstream rules for any value vlan");
-
-        //match: in port and any-vlan (coming from OLT app.)
-        //action: write metadata, go to table 1 and meter
-        FlowRule.Builder inner = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(fwd.selector())
-                .withTreatment(buildTreatment(Instructions.transition(QQ_TABLE), fetchMeter(fwd),
-                        fetchWriteMetadata(fwd)));
-
-        //match: in port and any-vlan (coming from OLT app.)
-        //action: immediate: push:QinQ, vlanId (s-tag), write metadata, meter and output
-        FlowRule.Builder outer = DefaultFlowRule.builder()
-                .fromApp(fwd.appId())
-                .forDevice(deviceId)
-                .forTable(QQ_TABLE)
-                .makePermanent()
-                .withPriority(fwd.priority())
-                .withSelector(fwd.selector())
-                .withTreatment(buildTreatment(outerPair.getLeft(), outerPair.getRight(),
-                        fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd), output));
-
-        applyRules(fwd, inner, outer);
-    }
-
-    private boolean checkNoneVlanCriteria(ForwardingObjective fwd) {
-        // Add the VLAN_PUSH treatment if we're matching on VlanId.NONE
-        Criterion vlanMatchCriterion = filterForCriterion(fwd.selector().criteria(), Criterion.Type.VLAN_VID);
-        boolean noneValueVlanStatus = false;
-        if (vlanMatchCriterion != null) {
-            noneValueVlanStatus = ((VlanIdCriterion) vlanMatchCriterion).vlanId().equals(VlanId.NONE);
-        }
-        return noneValueVlanStatus;
-    }
-
-    private boolean checkAnyVlanMatchCriteria(ForwardingObjective fwd) {
-        Criterion anyValueVlanCriterion = fwd.selector().criteria().stream()
-                .filter(c -> c.type().equals(Criterion.Type.VLAN_VID))
-                .filter(vc -> ((VlanIdCriterion) vc).vlanId().toShort() == VlanId.ANY_VALUE)
-                .findAny().orElse(null);
-
-        if (anyValueVlanCriterion == null) {
-            log.debug("Any value vlan match criteria is not found, criteria {}",
-                      fwd.selector().criteria());
-            return false;
-        }
-
-        return true;
-    }
-
-    private Instruction fetchOutput(ForwardingObjective fwd, String direction) {
-        Instruction output = fwd.treatment().allInstructions().stream()
-                .filter(i -> i.type() == Instruction.Type.OUTPUT)
-                .findFirst().orElse(null);
-
-        if (output == null) {
-            log.error("OLT {} rule has no output", direction);
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return null;
-        }
-        return output;
-    }
-
-    private Instruction fetchMeter(ForwardingObjective fwd) {
-        Instruction meter = fwd.treatment().metered();
-
-        if (meter == null) {
-            log.debug("Meter instruction is not found for the forwarding objective {}", fwd);
-            return null;
-        }
-
-        log.debug("Meter instruction is found.");
-        return meter;
-    }
-
-    private Instructions.MetadataInstruction fetchWriteMetadata(ForwardingObjective fwd) {
-        Instructions.MetadataInstruction writeMetadata = fwd.treatment().writeMetadata();
-
-        if (writeMetadata == null) {
-            log.warn("Write metadata is not found for the forwarding obj");
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return null;
-        }
-
-        log.debug("Write metadata is found {}", writeMetadata);
-        return writeMetadata;
-    }
-
-    private List<Pair<Instruction, Instruction>> vlanOps(ForwardingObjective fwd,
-                                                         L2ModificationInstruction.L2SubType type) {
-
-        List<Pair<Instruction, Instruction>> vlanOps = findVlanOps(
-                fwd.treatment().allInstructions(), type);
-
-        if (vlanOps == null || vlanOps.isEmpty()) {
-            String direction = type == L2ModificationInstruction.L2SubType.VLAN_POP
-                    ? DOWNSTREAM : UPSTREAM;
-            log.error("Missing vlan operations in {} forwarding: {}", direction, fwd);
-            fail(fwd, ObjectiveError.BADPARAMS);
-            return ImmutableList.of();
-        }
-        return vlanOps;
-    }
-
-
-    private List<Pair<Instruction, Instruction>> findVlanOps(List<Instruction> instructions,
-                                                             L2ModificationInstruction.L2SubType type) {
-
-        List<Instruction> vlanOperations = findL2Instructions(
-                type,
-                instructions);
-        List<Instruction> vlanSets = findL2Instructions(
-                L2ModificationInstruction.L2SubType.VLAN_ID,
-                instructions);
-
-        if (vlanOperations.size() != vlanSets.size()) {
-            return ImmutableList.of();
-        }
-
-        List<Pair<Instruction, Instruction>> pairs = Lists.newArrayList();
-
-        for (int i = 0; i < vlanOperations.size(); i++) {
-            pairs.add(new ImmutablePair<>(vlanOperations.get(i), vlanSets.get(i)));
-        }
-        return pairs;
-    }
-
-    private List<Instruction> findL2Instructions(L2ModificationInstruction.L2SubType subType,
-                                                 List<Instruction> actions) {
-        return actions.stream()
-                .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
-                .filter(i -> ((L2ModificationInstruction) i).subtype() == subType)
-                .collect(Collectors.toList());
-    }
-
-    private void provisionEthTypeBasedFilter(FilteringObjective filter,
-                                             EthTypeCriterion ethType,
-                                             Instructions.OutputInstruction output,
-                                             L2ModificationInstruction vlanId,
-                                             L2ModificationInstruction vlanPush) {
-
-        Instruction meter = filter.meta().metered();
-        Instruction writeMetadata = filter.meta().writeMetadata();
-
-        TrafficSelector selector = buildSelector(filter.key(), ethType);
-        TrafficTreatment treatment;
-
-        if (vlanPush == null || vlanId == null) {
-            treatment = buildTreatment(output, meter, writeMetadata);
-        } else {
-            // we need to push the vlan because it came untagged (ATT)
-            treatment = buildTreatment(output, meter, vlanPush, vlanId, writeMetadata);
-        }
-
-        buildAndApplyRule(filter, selector, treatment);
-
-    }
-
-    private void provisionIgmp(FilteringObjective filter, EthTypeCriterion ethType,
-                               IPProtocolCriterion ipProto,
-                               Instructions.OutputInstruction output,
-                               Instruction vlan, Instruction pcp) {
-
-        Instruction meter = filter.meta().metered();
-        Instruction writeMetadata = filter.meta().writeMetadata();
-
-        // uniTagMatch
-        VlanIdCriterion vlanId = (VlanIdCriterion) filterForCriterion(filter.conditions(),
-                Criterion.Type.VLAN_VID);
-
-        TrafficSelector selector = buildSelector(filter.key(), ethType, ipProto, vlanId);
-        TrafficTreatment treatment = buildTreatment(output, vlan, pcp, meter, writeMetadata);
-        buildAndApplyRule(filter, selector, treatment);
-    }
-
-    private void provisionDhcp(FilteringObjective filter, EthTypeCriterion ethType,
-                               IPProtocolCriterion ipProto,
-                               UdpPortCriterion udpSrcPort,
-                               UdpPortCriterion udpDstPort,
-                               Instruction vlanIdInstruction,
-                               Instruction vlanPcpInstruction,
-                               Instructions.OutputInstruction output) {
-
-        Instruction meter = filter.meta().metered();
-        Instruction writeMetadata = filter.meta().writeMetadata();
-
-        VlanIdCriterion matchVlanId = (VlanIdCriterion)
-                filterForCriterion(filter.conditions(), Criterion.Type.VLAN_VID);
-
-        TrafficSelector selector;
-        TrafficTreatment treatment;
-
-        if (matchVlanId != null) {
-            log.debug("Building selector with match VLAN, {}", matchVlanId);
-            // in case of TT upstream the packet comes tagged and the vlan is swapped.
-            selector = buildSelector(filter.key(), ethType, ipProto, udpSrcPort,
-                                     udpDstPort, matchVlanId);
-            treatment = buildTreatment(output, meter, writeMetadata,
-                                       vlanIdInstruction, vlanPcpInstruction);
-        } else {
-            log.debug("Building selector with no VLAN");
-            // in case of ATT upstream the packet comes in untagged and we need to push the vlan
-            selector = buildSelector(filter.key(), ethType, ipProto, udpSrcPort, udpDstPort);
-            treatment = buildTreatment(output, meter, vlanIdInstruction, writeMetadata);
-        }
-        //In case of downstream there will be no match on the VLAN, which is null,
-        // so it will just be output, meter, writeMetadata
-
-        buildAndApplyRule(filter, selector, treatment);
-    }
-
-    private void provisionPPPoED(FilteringObjective filter, EthTypeCriterion ethType,
-                                 Instruction vlanIdInstruction,
-                                 Instruction vlanPcpInstruction,
-                                 Instructions.OutputInstruction output) {
-        Instruction meter = filter.meta().metered();
-        Instruction writeMetadata = filter.meta().writeMetadata();
-
-        VlanIdCriterion matchVlanId = (VlanIdCriterion)
-                filterForCriterion(filter.conditions(), Criterion.Type.VLAN_VID);
-
-        TrafficSelector selector;
-        TrafficTreatment treatment;
-
-        if (matchVlanId != null) {
-            log.debug("Building pppoed selector with match VLAN {}.", matchVlanId);
-        } else {
-            log.debug("Building pppoed selector without match VLAN.");
-        }
-
-        selector = buildSelector(filter.key(), ethType, matchVlanId);
-        treatment = buildTreatment(output, meter, writeMetadata, vlanIdInstruction, vlanPcpInstruction);
-        buildAndApplyRule(filter, selector, treatment);
-    }
-
-    private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
-                                   TrafficTreatment treatment) {
-        FlowRule rule = DefaultFlowRule.builder()
-                .fromApp(filter.appId())
-                .forDevice(deviceId)
-                .forTable(0)
-                .makePermanent()
-                .withSelector(selector)
-                .withTreatment(treatment)
-                .withPriority(filter.priority())
-                .build();
-
-        if (accumulator != null) {
-            if (log.isDebugEnabled()) {
-                log.debug("Adding pair to batch: {}", Pair.of(filter, rule));
-            }
-            accumulator.add(Pair.of(filter, rule));
-        } else {
-            FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
-            switch (filter.type()) {
-                case PERMIT:
-                    opsBuilder.add(rule);
-                    break;
-                case DENY:
-                    opsBuilder.remove(rule);
-                    break;
-                default:
-                    log.warn("Unknown filter type : {}", filter.type());
-                    fail(filter, ObjectiveError.UNSUPPORTED);
-            }
-            applyFlowRules(ImmutableList.of(filter), opsBuilder);
-        }
-    }
-
-    private void applyRules(ForwardingObjective fwd, FlowRule.Builder... fwdBuilders) {
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        switch (fwd.op()) {
-            case ADD:
-                for (FlowRule.Builder fwdBuilder : fwdBuilders) {
-                    builder.add(fwdBuilder.build());
-                }
-                break;
-            case REMOVE:
-                for (FlowRule.Builder fwdBuilder : fwdBuilders) {
-                    builder.remove(fwdBuilder.build());
-                }
-                break;
-            case ADD_TO_EXISTING:
-                break;
-            case REMOVE_FROM_EXISTING:
-                break;
-            default:
-                log.warn("Unknown forwarding operation: {}", fwd.op());
-        }
-
-        applyFlowRules(ImmutableList.of(fwd), builder);
-
-
-    }
-
-    private void applyFlowRules(List<Objective> objectives, FlowRuleOperations.Builder builder) {
-        flowRuleService.apply(builder.build(new FlowRuleOperationsContext() {
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                objectives.forEach(obj -> {
-                    pass(obj);
-                });
-            }
-
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                objectives.forEach(obj -> {
-                    fail(obj, ObjectiveError.FLOWINSTALLATIONFAILED);
-                });
-
-            }
-        }));
-    }
-
-    // Builds the batch using the accumulated flow rules
-    private void sendFilters(List<Pair<FilteringObjective, FlowRule>> pairs) {
-        FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
-        log.debug("Sending batch of {} filter-objs", pairs.size());
-        List<Objective> filterObjs = Lists.newArrayList();
-        // Iterates over all accumulated flow rules and then build an unique batch
-        pairs.forEach(pair -> {
-            FilteringObjective filter = pair.getLeft();
-            FlowRule rule = pair.getRight();
-            switch (filter.type()) {
-                case PERMIT:
-                    flowOpsBuilder.add(rule);
-                    log.debug("Applying add filter-obj {} to device: {}", filter.id(), deviceId);
-                    filterObjs.add(filter);
-                    break;
-                case DENY:
-                    flowOpsBuilder.remove(rule);
-                    log.debug("Deleting flow rule {} to device: {}", rule, deviceId);
-                    filterObjs.add(filter);
-                    break;
-                default:
-                    fail(filter, ObjectiveError.UNKNOWN);
-                    log.warn("Unknown forwarding type {}", filter.type());
-            }
-        });
-        if (log.isDebugEnabled()) {
-            log.debug("Applying batch {}", flowOpsBuilder.build());
-        }
-        // Finally applies the operations
-        applyFlowRules(filterObjs, flowOpsBuilder);
-    }
-
-    private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
-        return criteria.stream()
-                .filter(c -> c.type().equals(type))
-                .limit(1)
-                .findFirst().orElse(null);
-    }
-
-    private TrafficSelector buildSelector(Criterion... criteria) {
-
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
-        Arrays.stream(criteria).filter(Objects::nonNull).forEach(sBuilder::add);
-
-        return sBuilder.build();
-    }
-
-    private TrafficTreatment buildTreatment(Instruction... instructions) {
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
-        Arrays.stream(instructions).filter(Objects::nonNull).forEach(tBuilder::add);
-
-        return tBuilder.build();
-    }
-
-    private Instruction writeMetadataIncludingOnlyTp(ForwardingObjective fwd) {
-
-        return Instructions.writeMetadata(
-                fetchWriteMetadata(fwd).metadata() & 0xFFFF00000000L, 0L);
-    }
-
-    private void fail(Objective obj, ObjectiveError error) {
-        obj.context().ifPresent(context -> context.onError(obj, error));
-    }
-
-    private void pass(Objective obj) {
-        obj.context().ifPresent(context -> context.onSuccess(obj));
-    }
-
-
-    private class InnerGroupListener implements GroupListener {
-        @Override
-        public void event(GroupEvent event) {
-            GroupKey key = event.subject().appCookie();
-            NextObjective obj = pendingGroups.getIfPresent(key);
-            if (obj == null) {
-                log.debug("No pending group for {}, moving on", key);
-                return;
-            }
-            log.trace("Event {} for group {}, handling pending" +
-                              "NextGroup {}", event.type(), key, obj.id());
-            if (event.type() == GroupEvent.Type.GROUP_ADDED ||
-                    event.type() == GroupEvent.Type.GROUP_UPDATED) {
-                    flowObjectiveStore.putNextGroup(obj.id(), new OLTPipelineGroup(key));
-                    pass(obj);
-                    pendingGroups.invalidate(key);
-            } else if (event.type() == GroupEvent.Type.GROUP_REMOVED) {
-                    flowObjectiveStore.removeNextGroup(obj.id());
-                    pass(obj);
-                    pendingGroups.invalidate(key);
-            }
-        }
-    }
-
-    private static class OLTPipelineGroup implements NextGroup {
-
-        private final GroupKey key;
-
-        public OLTPipelineGroup(GroupKey key) {
-            this.key = key;
-        }
-
-        public GroupKey key() {
-            return key;
-        }
-
-        @Override
-        public byte[] data() {
-            return appKryo.serialize(key);
-        }
-
-    }
-
-    @Override
-    public List<String> getNextMappings(NextGroup nextGroup) {
-        // TODO Implementation deferred to vendor
-        return null;
-    }
-
-    // Flow rules accumulator for reducing the number of transactions required to the devices.
-    private final class ObjectiveAccumulator
-            extends AbstractAccumulator<Pair<FilteringObjective, FlowRule>> {
-
-        ObjectiveAccumulator(int maxFilter, int maxBatchMS, int maxIdleMS) {
-            super(TIMER, maxFilter, maxBatchMS, maxIdleMS);
-        }
-
-        @Override
-        public void processItems(List<Pair<FilteringObjective, FlowRule>> pairs) {
-            // Triggers creation of a batch using the list of flowrules generated from objs.
-            accumulatorExecutorService.execute(new FlowRulesBuilderTask(pairs));
-        }
-    }
-
-    // Task for building batch of flow rules in a separate thread.
-    private final class FlowRulesBuilderTask implements Runnable {
-        private final List<Pair<FilteringObjective, FlowRule>> pairs;
-
-        FlowRulesBuilderTask(List<Pair<FilteringObjective, FlowRule>> pairs) {
-            this.pairs = pairs;
-        }
-
-        @Override
-        public void run() {
-            try {
-                sendFilters(pairs);
-            } catch (Exception e) {
-                log.warn("Unable to send objectives", e);
-            }
-        }
-    }
-}
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index d63638b..48cb791 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -173,49 +173,6 @@
                    impl="org.onosproject.driver.traceable.OfdpaPipelineTraceable" />
     </driver>
 
-    <driver name="celestica" extends="default"
-            manufacturer="PMC GPON Networks" hwVersion="PAS5211 v2" swVersion="vOLT version 1.5.3.*">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.OltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-    </driver>
-    <driver name="pmc-olt" extends="default"
-            manufacturer="PMC GPON Networks" hwVersion="PASffffffff v-1" swVersion="vOLT.*">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.OltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-    </driver>
-    <driver name="voltha" extends="default"
-            manufacturer="VOLTHA Project" hwVersion=".*" swVersion=".*">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.OltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-        <property name="accumulatorEnabled">true</property>
-    </driver>
-    <driver name="fj-olt" extends="default"
-            manufacturer="Fujitsu" hwVersion="svkOLT" swVersion="v1.0">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.OltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-    </driver>
-    <driver name="nokia-olt" extends="default"
-            manufacturer="Nokia" hwVersion="SDOLT" swVersion="5.2.1">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.NokiaOltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-    </driver>
-    <driver name="g.fast" extends="default"
-            manufacturer="TEST1" hwVersion="TEST2" swVersion="TEST3">
-        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
-                   impl="org.onosproject.driver.pipeline.OltPipeline"/>
-        <behaviour api="org.onosproject.net.behaviour.MeterQuery"
-                   impl="org.onosproject.driver.query.FullMetersAvailable"/>
-    </driver>
     <!--  The SoftRouter driver is meant to be used by any software/NPU based
        ~  switch that wishes to implement a simple 2-table router. To use this
        ~  driver, configure ONOS with the dpid of the device, or extend the