[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);
+ }
+ }
+}