Added an OLT application which pushes vlan circuits when ports are up.
Added a driver for the OLT
Change-Id: I13085d4a5a05e92a1640eff3f10ff75c2188e0d3
diff --git a/apps/olt/pom.xml b/apps/olt/pom.xml
new file mode 100644
index 0000000..73dbcc7
--- /dev/null
+++ b/apps/olt/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2014 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-olt</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>OLT application</description>
+
+ <properties>
+ <onos.app.name>org.onosproject.olt</onos.app.name>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr</artifactId>
+ <version>1.8.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>5.0.0</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/apps/olt/src/main/java/org/onosproject/olt/OLT.java b/apps/olt/src/main/java/org/onosproject/olt/OLT.java
new file mode 100644
index 0000000..6ec7a6f
--- /dev/null
+++ b/apps/olt/src/main/java/org/onosproject/olt/OLT.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2014 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.olt;
+
+
+import com.google.common.base.Strings;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Tools;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+
+import java.util.Dictionary;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Sample mobility application. Cleans up flowmods when a host moves.
+ */
+@Component(immediate = true)
+public class OLT {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+
+ private ApplicationId appId;
+
+ public static final int UPLINK_PORT = 129;
+
+ public static final String OLT_DEVICE = "of:90e2ba82f97791e9";
+
+ @Property(name = "uplinkPort", intValue = UPLINK_PORT,
+ label = "The OLT's uplink port number")
+ private int uplinkPort = UPLINK_PORT;
+
+ //TODO: replace this with an annotation lookup
+ @Property(name = "oltDevice", value = OLT_DEVICE,
+ label = "The OLT device id")
+ private String oltDevice = OLT_DEVICE;
+
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication("org.onosproject.mobility");
+ deviceService.getPorts(DeviceId.deviceId(oltDevice)).stream().forEach(
+ port -> {
+ if (port.isEnabled()) {
+ provisionVlanOnPort(port.number());
+ }
+ }
+ );
+ log.info("Started with Application ID {}", appId.id());
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Modified
+ public void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+
+
+ String s = Tools.get(properties, "uplinkPort");
+ uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);
+
+ s = Tools.get(properties, "oltDevice");
+ oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;
+
+ }
+
+ private void provisionVlanOnPort(PortNumber p) {
+ long port = p.toLong();
+ if (port > 4095) {
+ log.warn("Port Number {} exceeds vlan max", port);
+ return;
+ }
+
+ TrafficSelector upstream = DefaultTrafficSelector.builder()
+ .matchVlanId(
+ VlanId.vlanId((short) port))
+ .matchInPort(p)
+ .build();
+
+ TrafficSelector downStream = DefaultTrafficSelector.builder()
+ .matchVlanId(
+ VlanId.vlanId((short) port))
+ .matchInPort(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment downStreamTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(p)
+ .build();
+
+
+ ForwardingObjective upFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(upstream)
+ .fromApp(appId)
+ .withTreatment(upstreamTreatment)
+ .add();
+
+ ForwardingObjective downFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(downStream)
+ .fromApp(appId)
+ .withTreatment(downStreamTreatment)
+ .add();
+
+ flowObjectiveService.forward(DeviceId.deviceId(oltDevice), upFwd);
+ flowObjectiveService.forward(DeviceId.deviceId(oltDevice), downFwd);
+
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+ @Override
+ public void event(DeviceEvent event) {
+ DeviceId devId = DeviceId.deviceId(oltDevice);
+ switch (event.type()) {
+ case PORT_ADDED:
+ case PORT_UPDATED:
+ if (devId.equals(event.subject().id()) && event.port().isEnabled()) {
+ provisionVlanOnPort(event.port().number());
+ }
+ break;
+ case DEVICE_ADDED:
+ case DEVICE_UPDATED:
+ case DEVICE_REMOVED:
+ case DEVICE_SUSPENDED:
+ case DEVICE_AVAILABILITY_CHANGED:
+ case PORT_REMOVED:
+ case PORT_STATS_UPDATED:
+ default:
+ return;
+ }
+ }
+ }
+
+
+}
+
+
diff --git a/apps/olt/src/main/java/org/onosproject/olt/package-info.java b/apps/olt/src/main/java/org/onosproject/olt/package-info.java
new file mode 100644
index 0000000..b0954e5
--- /dev/null
+++ b/apps/olt/src/main/java/org/onosproject/olt/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 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.
+ */
+
+/**
+ * OLT application handling PMC OLT hardware.
+ */
+package org.onosproject.olt;
diff --git a/apps/pom.xml b/apps/pom.xml
index 69f767b..dcc0ddd 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -50,6 +50,7 @@
<module>cordfabric</module>
<module>xos-integration</module>
<module>pcep-api</module>
+ <module>olt</module>
</modules>
<properties>
diff --git a/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java b/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
new file mode 100644
index 0000000..c360c90
--- /dev/null
+++ b/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
@@ -0,0 +1,146 @@
+/*
+ * 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.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+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.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.instructions.Instructions;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Simple single table pipeline abstraction.
+ */
+public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
+
+ private final Logger log = getLogger(getClass());
+
+ private ServiceDirectory serviceDirectory;
+ private FlowRuleService flowRuleService;
+ private DeviceId deviceId;
+
+ @Override
+ public void init(DeviceId deviceId, PipelinerContext context) {
+ this.serviceDirectory = context.directory();
+ this.deviceId = deviceId;
+
+ flowRuleService = serviceDirectory.get(FlowRuleService.class);
+ }
+
+ @Override
+ public void filter(FilteringObjective filter) {
+ throw new UnsupportedOperationException("Single table does not filter.");
+ }
+
+ @Override
+ public void forward(ForwardingObjective fwd) {
+ FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
+
+ if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
+ throw new UnsupportedOperationException(
+ "Only VERSATILE is supported.");
+ }
+
+ boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> {
+ if (i instanceof Instructions.OutputInstruction) {
+ Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
+ return out.port().equals(PortNumber.CONTROLLER);
+ }
+ return false;
+ });
+
+ if (isPunt) {
+ return;
+ }
+
+ TrafficSelector selector = fwd.selector();
+ TrafficTreatment treatment = fwd.treatment();
+ if ((fwd.treatment().deferred().size() == 0) &&
+ (fwd.treatment().immediate().size() == 0) &&
+ (fwd.treatment().tableTransition() == null) &&
+ (!fwd.treatment().clearedDeferred())) {
+ TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder();
+ flowTreatment.add(Instructions.createDrop());
+ treatment = flowTreatment.build();
+ }
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector)
+ .withTreatment(fwd.treatment())
+ .fromApp(fwd.appId())
+ .withPriority(fwd.priority());
+
+ if (fwd.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(fwd.timeout());
+ }
+
+
+ switch (fwd.op()) {
+
+ case ADD:
+ flowBuilder.add(ruleBuilder.build());
+ break;
+ case REMOVE:
+ flowBuilder.remove(ruleBuilder.build());
+ break;
+ default:
+ log.warn("Unknown operation {}", fwd.op());
+ }
+
+ flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ if (fwd.context().isPresent()) {
+ fwd.context().get().onSuccess(fwd);
+ }
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ if (fwd.context().isPresent()) {
+ fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
+ }
+ }
+ }));
+
+ }
+
+ @Override
+ public void next(NextObjective nextObjective) {
+ throw new UnsupportedOperationException("Single table does not next hop.");
+ }
+
+}
diff --git a/drivers/src/main/resources/onos-drivers.xml b/drivers/src/main/resources/onos-drivers.xml
index f9c648e..4488299 100644
--- a/drivers/src/main/resources/onos-drivers.xml
+++ b/drivers/src/main/resources/onos-drivers.xml
@@ -62,6 +62,11 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/>
</driver>
+ <driver name="pmc-olt" extends="default"
+ manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5">
+ <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+ impl="org.onosproject.driver.pipeline.OLTPipeline"/>
+ </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