aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java')
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java286
1 files changed, 286 insertions, 0 deletions
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
new file mode 100644
index 00000000..7a92b4fa
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
@@ -0,0 +1,286 @@
+/*
+ * 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 org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onosproject.core.ApplicationId;
+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.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.Criterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.UdpPortCriterion;
+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;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Driver for OpenstackSwitching.
+ */
+public class OpenstackPipeline extends DefaultSingleTablePipeline
+ implements Pipeliner {
+
+ private final Logger log = getLogger(getClass());
+ private CoreService coreService;
+ private ServiceDirectory serviceDirectory;
+ protected FlowObjectiveStore flowObjectiveStore;
+ protected DeviceId deviceId;
+ protected ApplicationId appId;
+ protected FlowRuleService flowRuleService;
+
+ protected static final int VNI_TABLE = 0;
+ protected static final int FORWARDING_TABLE = 1;
+
+ private static final int DROP_PRIORITY = 0;
+ private static final int TIME_OUT = 0;
+ private static final int DHCP_SERVER_PORT = 67;
+ private static final int DHCP_CLIENT_PORT = 68;
+
+
+ @Override
+ public void init(DeviceId deviceId, PipelinerContext context) {
+ super.init(deviceId, context);
+ this.serviceDirectory = context.directory();
+ this.deviceId = deviceId;
+
+ coreService = serviceDirectory.get(CoreService.class);
+ flowRuleService = serviceDirectory.get(FlowRuleService.class);
+ flowObjectiveStore = context.store();
+
+ appId = coreService.registerApplication(
+ "org.onosproject.driver.OpenstackPipeline");
+
+ initializePipeline();
+ }
+
+ @Override
+ public void filter(FilteringObjective filteringObjective) {
+ super.filter(filteringObjective);
+ }
+
+ @Override
+ public void next(NextObjective nextObjective) {
+ super.next(nextObjective);
+ }
+
+ @Override
+ public void forward(ForwardingObjective forwardingObjective) {
+ Collection<FlowRule> rules;
+ FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
+
+ rules = processForward(forwardingObjective);
+
+ switch (forwardingObjective.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(forwardingObjective, ObjectiveError.UNKNOWN);
+ log.warn("Unknown forwarding type {}");
+ }
+
+ flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ pass(forwardingObjective);
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
+ }
+ }));
+ }
+
+ private void initializePipeline() {
+ processVNITable(true);
+ processForwardingTable(true);
+ }
+
+ private void processVNITable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.transition(FORWARDING_TABLE);
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(VNI_TABLE)
+ .build();
+
+ applyRules(install, flowRule);
+ }
+
+ private void processForwardingTable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(FORWARDING_TABLE)
+ .build();
+
+ applyRules(install, flowRule);
+ }
+
+ private void applyRules(boolean install, FlowRule flowRule) {
+ FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
+
+ flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
+
+ flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.debug("Provisioned vni or forwarding table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.debug("Failed to privision vni or forwarding table");
+ }
+ }));
+ }
+
+ private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
+ switch (forwardingObjective.flag()) {
+ case SPECIFIC:
+ return processSpecific(forwardingObjective);
+ case VERSATILE:
+ return processVersatile(forwardingObjective);
+ default:
+ fail(forwardingObjective, ObjectiveError.UNKNOWN);
+ log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
+ }
+ return Collections.emptySet();
+ }
+
+ private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
+ log.debug("Processing versatile forwarding objective");
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(forwardingObjective.selector())
+ .withTreatment(forwardingObjective.treatment())
+ .withPriority(forwardingObjective.priority())
+ .fromApp(forwardingObjective.appId());
+
+ if (forwardingObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(TIME_OUT);
+ }
+
+ //ARP & DHCP Rule
+ EthTypeCriterion ethCriterion =
+ (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE);
+ UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective
+ .selector().getCriterion(Criterion.Type.UDP_DST);
+ if (ethCriterion != null) {
+ if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
+ ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
+ ruleBuilder.forTable(VNI_TABLE);
+ return Collections.singletonList(ruleBuilder.build());
+ } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
+ ruleBuilder.forTable(VNI_TABLE);
+ return Collections.singletonList(ruleBuilder.build());
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
+ log.debug("Processing specific forwarding objective");
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(forwardingObjective.selector())
+ .withTreatment(forwardingObjective.treatment())
+ .withPriority(forwardingObjective.priority())
+ .fromApp(forwardingObjective.appId());
+
+ if (forwardingObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(TIME_OUT);
+ }
+
+ //VNI Table Rule
+ if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
+ tBuilder.transition(FORWARDING_TABLE);
+ ruleBuilder.withTreatment(tBuilder.build());
+ ruleBuilder.forTable(VNI_TABLE);
+ } else {
+ ruleBuilder.forTable(FORWARDING_TABLE);
+ }
+
+ return Collections.singletonList(ruleBuilder.build());
+ }
+
+
+ private void pass(Objective obj) {
+ if (obj.context().isPresent()) {
+ obj.context().get().onSuccess(obj);
+ }
+ }
+
+ private void fail(Objective obj, ObjectiveError error) {
+ if (obj.context().isPresent()) {
+ obj.context().get().onError(obj, error);
+ }
+ }
+}
+