initial flows for corsa pipeline v39

- initial flows configuration
- moved to a dedicated folder
- refactoring super classes

Change-Id: Ie7452aed35d7947ca5f7246dd06fcbb87b2971b5
diff --git a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java
new file mode 100644
index 0000000..581a734
--- /dev/null
+++ b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.corsa;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+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.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.DefaultMeterRequest;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterRequest;
+import org.slf4j.Logger;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.onosproject.net.flow.FlowRule.Builder;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the Corsa pipeline handler for pipeline version 3.
+ */
+public class CorsaPipelineV3 extends AbstractCorsaPipeline {
+
+    private final Logger log = getLogger(getClass());
+
+    protected static final int PORT_BASED_PROTO_TABLE = 0;
+    protected static final int VLAN_CHECK_TABLE = 1;
+    protected static final int VLAN_MAC_XLATE_TABLE = 2;
+    protected static final int VLAN_CIRCUIT_TABLE = 3;
+    protected static final int PRIORITY_MAP_TABLE = 4;
+    protected static final int L3_IF_MAC_DA_TABLE = 5;
+    protected static final int ETHER_TABLE = 6;
+    protected static final int FIB_TABLE = 7;
+    protected static final int LOCAL_TABLE = 9;
+
+    protected static final byte MAX_VLAN_PCP = 7;
+
+    protected MeterId defaultMeterId = null;
+
+    @Override
+    protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) {
+        TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
+
+        treatment.immediate().stream()
+                .filter(i -> {
+                    switch (i.type()) {
+                        case L2MODIFICATION:
+                            L2ModificationInstruction l2i = (L2ModificationInstruction) i;
+                            if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
+                                    l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
+                                return true;
+                            }
+                        case OUTPUT:
+                            return true;
+                        default:
+                            return false;
+                    }
+                }).forEach(i -> tb.add(i));
+        return tb.build();
+    }
+
+    @Override
+    protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
+        return DefaultTrafficTreatment.builder().deferred();
+    }
+
+    @Override
+    protected Builder processSpecificRoutingRule(Builder rb) {
+        return rb.forTable(FIB_TABLE);
+    }
+
+    @Override
+    protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
+        TrafficSelector filteredSelector =
+                DefaultTrafficSelector.builder()
+                        .matchInPort(
+                                ((PortCriterion) fwd.selector().getCriterion(Criterion.Type.IN_PORT)).port())
+                        .matchVlanId(
+                                ((VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID)).vlanId())
+                        .build();
+
+        Builder ruleBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .withPriority(fwd.priority())
+                .forDevice(deviceId)
+                .withSelector(filteredSelector)
+                .withTreatment(fwd.treatment())
+                .forTable(VLAN_CIRCUIT_TABLE);
+
+        if (fwd.permanent()) {
+            ruleBuilder.makePermanent();
+        } else {
+            ruleBuilder.makeTemporary(fwd.timeout());
+        }
+
+        return Collections.singletonList(ruleBuilder.build());
+    }
+
+    @Override
+    protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, Builder rule) {
+        //TODO
+        return Collections.emptyList();
+    }
+
+    @Override
+    protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, Builder rule) {
+        //TODO
+        return Collections.emptyList();
+    }
+
+    @Override
+    protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, Builder rule) {
+        //TODO
+        return Collections.emptyList();
+    }
+
+    @Override
+    protected Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
+                         log.debug("adding rule for MAC: {}", eth.mac());
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        selector.matchEthDst(eth.mac());
+        selector.matchInPort(port.port());
+        treatment.transition(ETHER_TABLE);
+        return DefaultFlowRule.builder()
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .makePermanent()
+                .forTable(L3_IF_MAC_DA_TABLE);
+    }
+
+    @Override
+    protected Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
+        log.debug("adding rule for VLAN: {}", vlan.vlanId());
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        selector.matchVlanId(vlan.vlanId());
+        selector.matchInPort(port.port());
+                /* Static treatment for VLAN_CIRCUIT_TABLE */
+        treatment.setVlanPcp(MAX_VLAN_PCP);
+        treatment.setQueue(0);
+        treatment.meter(MeterId.meterId(defaultMeterId.id())); /* use default meter (Green) */
+        treatment.transition(L3_IF_MAC_DA_TABLE);
+        return DefaultFlowRule.builder()
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .makePermanent()
+                .forTable(VLAN_CIRCUIT_TABLE);
+    }
+
+    @Override
+    protected Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
+        log.debug("adding rule for IP: {}", ip.ip());
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        selector.matchEthType(Ethernet.TYPE_IPV4);
+        selector.matchIPDst(ip.ip());
+        treatment.transition(LOCAL_TABLE);
+        return DefaultFlowRule.builder()
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(HIGHEST_PRIORITY)
+                .makePermanent()
+                .forTable(FIB_TABLE);
+    }
+
+    @Override
+    public void initializePipeline() {
+        processMeterTable(true);
+        processPortBasedProtoTable(true); /* Table 0 */
+        processVlanCheckTable(true);      /* Table 1 */
+        processVlanMacXlateTable(true);   /* Table 2 */
+        processVlanCircuitTable(true);    /* Table 3 */
+        processPriorityMapTable(true);    /* Table 4 */
+        processL3IFMacDATable(true);      /* Table 5 */
+        processEtherTable(true);          /* Table 6 */
+        processFibTable(true);            /* Table 7 */
+        processLocalTable(true);          /* Table 9 */
+    }
+
+    protected void processMeterTable(boolean install) {
+        //Green meter : Pass all traffic
+        Band dropBand = DefaultBand.builder()
+                .ofType(Band.Type.DROP)
+                .withRate(0xFFFFFFFF)   /* Max Rate */
+                .build();
+        MeterRequest.Builder ops = DefaultMeterRequest.builder()
+                .forDevice(deviceId)
+                .withBands(Collections.singletonList(dropBand))
+                .fromApp(appId);
+
+        Meter meter = meterService.submit(install ? ops.add() : ops.remove());
+        defaultMeterId = meter.id();
+    }
+
+    protected void processPortBasedProtoTable(boolean install) {
+        /* Default action */
+        processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE, "Provisioned port-based table");
+    }
+
+    protected void processVlanCheckTable(boolean install) {
+
+        /* Default action */
+        processTableMissDrop(install, VLAN_CHECK_TABLE, "Provisioned vlantable drop");
+
+        processTaggedPackets(install);
+
+    }
+
+    /* Tagged packets to VLAN_MAC_XLATE */
+    protected void processTaggedPackets(boolean install) {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchVlanId(VlanId.ANY);
+
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        treatment.transition(VLAN_MAC_XLATE_TABLE);
+
+        FlowRule rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(VLAN_CHECK_TABLE).build();
+        processFlowRule(install, rule, "Provisioned vlan table tagged packets");
+    }
+
+    protected void processVlanMacXlateTable(boolean install) {
+        /* Default action */
+        processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE, "Provisioned vlan mac table");
+    }
+
+    protected void processVlanCircuitTable(boolean install) {
+        /* Default action */
+        processTableMissDrop(install, VLAN_CIRCUIT_TABLE, "Provisioned vlan circuit");
+    }
+
+    private void processPriorityMapTable(boolean install) {
+        /* Not required currently */
+    }
+
+    protected void processL3IFMacDATable(boolean install) {
+        int table = L3_IF_MAC_DA_TABLE;
+
+        /* Default action */
+        processTableMissDrop(install, table, "Provisioned l3 table drop");
+
+        /* Allow MAC broadcast frames on all ports */
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthDst(MacAddress.BROADCAST);
+
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        treatment.transition(ETHER_TABLE);
+
+        FlowRule rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(table).build();
+        processFlowRule(install, rule, "Provisioned l3 table");
+    }
+
+
+    protected void processEtherTable(boolean install) {
+        int table = ETHER_TABLE;
+
+        /* Default action */
+        processTableMissDrop(install, table, "Provisioned ether type table drop");
+
+        /* Arp to controller */
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_ARP);
+
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        treatment.punt();
+
+        FlowRule rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(table).build();
+        processFlowRule(install, rule, "Provisioned ether type table arp");
+
+        /* IP to FIB_TABLE */
+        selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_IPV4);
+
+        treatment = DefaultTrafficTreatment.builder();
+        treatment.transition(FIB_TABLE);
+
+        rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(table).build();
+        processFlowRule(install, rule, "Provisioned ether type table ip");
+    }
+
+    private void processFibTable(boolean install) {
+        /* Default action */
+        processTableMissDrop(install, FIB_TABLE, "Provisioned fib drop");
+    }
+
+    private void processLocalTable(boolean install) {
+        int table = LOCAL_TABLE;
+        /* Default action */
+        processTableMissDrop(install, table, "Provisioned local table drop");
+
+        /* Send all protocols to controller */
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        treatment.punt();
+
+        FlowRule rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(CONTROLLER_PRIORITY)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(table).build();
+        processFlowRule(install, rule, "Provisioned ether type table to controller");
+    }
+
+
+}