[ONOS-2384]Driver for standard OpenVSwitch 

Change-Id: I54b32c1cf1088ecc51e672c557c726215ba83fb0
diff --git a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
index 495fa00..1b2e9be 100644
--- a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
@@ -117,7 +117,6 @@
     private DeviceListener deviceListener = new InnerDeviceListener();
     private static final String IFACEID = "ifaceid";
     private static final String PORT_HEAD = "vxlan";
-    private static final int MAC_TABLE = 40;
     private static final String DEFAULT_BRIDGE_NAME = "br-int";
     private static final String CONTROLLER_IP_KEY = "ipaddress";
 
@@ -463,7 +462,6 @@
         TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
         treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId
                 .toString())));
-        treatment.transition(MAC_TABLE);
         ForwardingObjective.Builder objective = DefaultForwardingObjective
                 .builder().withTreatment(treatment.build())
                 .withSelector(selector).fromApp(appId).makePermanent()
@@ -484,8 +482,7 @@
                 .matchInPort(inPort)
                 .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
                              .toString()))).build();
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .transition(MAC_TABLE).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
 
         ForwardingObjective.Builder objective = DefaultForwardingObjective
                 .builder().withTreatment(treatment).withSelector(selector)
@@ -501,8 +498,7 @@
     private void programPortDefaultRules(DeviceId dpid, ApplicationId appid,
                                          Objective.Operation type) {
         TrafficSelector selector = DefaultTrafficSelector.builder().build();
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .transition(MAC_TABLE).build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
         ForwardingObjective.Builder objective = DefaultForwardingObjective
                 .builder().withTreatment(treatment).withSelector(selector)
                 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
diff --git a/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
new file mode 100644
index 0000000..fd728e9
--- /dev/null
+++ b/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.pipeline;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+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.Criterion.Type;
+import org.onosproject.net.flow.instructions.Instructions;
+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.slf4j.Logger;
+
+/**
+ * Driver for standard OpenVSwitch.
+ */
+public class OpenVSwitchPipeline extends AbstractHandlerBehaviour
+        implements Pipeliner {
+
+    private final Logger log = getLogger(getClass());
+    private CoreService coreService;
+    private ServiceDirectory serviceDirectory;
+    protected FlowObjectiveStore flowObjectiveStore;
+    protected DeviceId deviceId;
+    protected FlowRuleService flowRuleService;
+    protected DeviceService deviceService;
+    private static final int MAC_TABLE_PRIORITY = 0xffff;
+    private static final int PORT_TABLE_PRIORITY = 0xffff;
+    private static final int TIME_OUT = 0;
+    private static final int MAC_TABLE = 40;
+    private static final int PORT_TABLE = 0;
+
+    @Override
+    public void init(DeviceId deviceId, PipelinerContext context) {
+        this.serviceDirectory = context.directory();
+        this.deviceId = deviceId;
+
+        coreService = serviceDirectory.get(CoreService.class);
+        flowRuleService = serviceDirectory.get(FlowRuleService.class);
+        flowObjectiveStore = context.store();
+        coreService
+                .registerApplication("org.onosproject.driver.OpenVSwitchPipeline");
+
+    }
+
+    @Override
+    public void filter(FilteringObjective filteringObjective) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void forward(ForwardingObjective fwd) {
+        Collection<FlowRule> rules;
+        FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations
+                .builder();
+
+        rules = processForward(fwd);
+        switch (fwd.op()) {
+        case ADD:
+            rules.stream().filter(rule -> rule != null)
+                    .forEach(flowOpsBuilder::add);
+            break;
+        case REMOVE:
+            rules.stream().filter(rule -> rule != null)
+                    .forEach(flowOpsBuilder::remove);
+            break;
+        default:
+            fail(fwd, ObjectiveError.UNKNOWN);
+            log.warn("Unknown forwarding type {}", fwd.op());
+        }
+
+        flowRuleService.apply(flowOpsBuilder
+                .build(new FlowRuleOperationsContext() {
+                    @Override
+                    public void onSuccess(FlowRuleOperations ops) {
+                        pass(fwd);
+                    }
+
+                    @Override
+                    public void onError(FlowRuleOperations ops) {
+                        fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
+                    }
+                }));
+    }
+
+    @Override
+    public void next(NextObjective nextObjective) {
+        // TODO Auto-generated method stub
+
+    }
+
+    private Collection<FlowRule> processForward(ForwardingObjective fwd) {
+        switch (fwd.flag()) {
+        case SPECIFIC:
+            return processSpecific(fwd);
+        case VERSATILE:
+            return processVersatile(fwd);
+        default:
+            fail(fwd, ObjectiveError.UNKNOWN);
+            log.warn("Unknown forwarding flag {}", fwd.flag());
+        }
+        return Collections.emptySet();
+    }
+
+    private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
+        log.debug("Processing versatile forwarding objective");
+        return Collections.emptyList();
+    }
+
+    private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
+        log.debug("Processing specific forwarding objective");
+        TrafficSelector selector = fwd.selector();
+        TrafficTreatment tb = fwd.treatment();
+        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId()).withPriority(fwd.priority())
+                .forDevice(deviceId).withSelector(selector)
+                .makeTemporary(TIME_OUT);
+
+        if (fwd.permanent()) {
+            ruleBuilder.makePermanent();
+        }
+        if (selector.getCriterion(Type.ETH_DST) != null
+                || tb.allInstructions().contains(Instructions.createDrop())) {
+            ruleBuilder.withPriority(MAC_TABLE_PRIORITY);
+            ruleBuilder.withTreatment(tb);
+            ruleBuilder.forTable(MAC_TABLE);
+        } else {
+            ruleBuilder.withPriority(PORT_TABLE_PRIORITY);
+            TrafficTreatment.Builder newTraffic = DefaultTrafficTreatment.builder();
+            tb.allInstructions().forEach(t -> newTraffic.add(t));
+            newTraffic.transition(MAC_TABLE);
+            ruleBuilder.withTreatment(newTraffic.build());
+            ruleBuilder.forTable(PORT_TABLE);
+        }
+        return Collections.singletonList(ruleBuilder.build());
+    }
+
+    private void fail(Objective obj, ObjectiveError error) {
+        if (obj.context().isPresent()) {
+            obj.context().get().onError(obj, error);
+        }
+    }
+
+    private void pass(Objective obj) {
+        if (obj.context().isPresent()) {
+            obj.context().get().onSuccess(obj);
+        }
+    }
+}