alshabib
Committed by Gerrit Code Review

Low level openflow drivers have been promoted to the driver subsystem.

All new device drivers should provide a handshaking behaviour as well
as well as a pipeline behaviour.

Change-Id: I883830b074e5d254a8cc6100e6c4fa0023594a36
Showing 30 changed files with 386 additions and 1144 deletions
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
<repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
<bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-of-api/${project.version}</bundle>
</feature>
</features>
......@@ -48,6 +48,11 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-of-api</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......
/*
* Copyright 2014-2015 Open Networking Laboratory
* 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.
......@@ -13,88 +13,58 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openflow.drivers;
package org.onosproject.driver.handshaker;
import java.util.Collections;
import java.util.List;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.protocol.OFVersion;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Nicira, Inc. Make
* (Hardware Desc.) : Open vSwitch Model (Datapath Desc.) : None Software :
* 1.11.90 (or whatever version + build) Serial : None
* Default driver to fallback on if no other driver is available.
*/
public class OFSwitchImplOVS10 extends AbstractOpenFlowSwitch {
public class DefaultSwitchHandShaker extends AbstractOpenFlowSwitch {
private static final int LOWEST_PRIORITY = 0;
public OFSwitchImplOVS10(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
setSwitchDescription(desc);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "OFSwitchImplOVS10 [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
}
@Override
public Boolean supportNxRole() {
if (this.factory().getVersion() == OFVersion.OF_10) {
return true;
}
return false;
}
@Override
public void startDriverHandshake() {
if (factory().getVersion() == OFVersion.OF_10) {
OFFlowAdd.Builder fmBuilder = factory().buildFlowAdd();
fmBuilder.setPriority(LOWEST_PRIORITY);
write(fmBuilder.build());
sendMsg(fmBuilder.build());
}
@Override
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {}
@Override
public void write(OFMessage msg) {
channel.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
channel.write(msgs);
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public List<OFPortDesc> getPorts() {
if (this.factory().getVersion() == OFVersion.OF_10) {
return Collections.unmodifiableList(features.getPorts());
} else {
return Collections.unmodifiableList(
ports.stream().flatMap(p -> p.getEntries().stream())
.collect(Collectors.toList()));
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
......
/*
* 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.handshaker;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.TableId;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
//import java.util.ArrayList;
/**
* Corsa switch driver for BGP Router deployment.
*/
public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
private AtomicBoolean handShakeComplete = new AtomicBoolean(false);
private int barrierXid;
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void startDriverHandshake() {
if (startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeAlreadyStarted();
}
startDriverHandshakeCalled = true;
OFFlowMod fm = factory().buildFlowDelete()
.setTableId(TableId.ALL)
.setOutGroup(OFGroup.ANY)
.build();
sendMsg(Collections.singletonList(fm));
barrierXid = getNextTransactionId();
OFBarrierRequest barrier = factory().buildBarrierRequest()
.setXid(barrierXid).build();
sendMsg(Collections.singletonList(barrier));
}
@Override
public boolean isDriverHandshakeComplete() {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeAlreadyStarted();
}
return handShakeComplete.get();
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
if (handShakeComplete.get()) {
throw new SwitchDriverSubHandshakeCompleted(m);
}
if (m.getType() == OFType.BARRIER_REPLY &&
m.getXid() == barrierXid) {
handShakeComplete.set(true);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
* 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.
......@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.handshaker;
/**
* OpenFlow base switch drivers implementations.
*/
package org.onosproject.openflow.drivers;
public class OFOVSSwitchCorsaTTP extends OFCorsaSwitchDriver {
}
......
/*
* Copyright 2014-2015 Open Networking Laboratory
* 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.
......@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openflow.drivers;
package org.onosproject.driver.handshaker;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
......@@ -23,14 +22,12 @@ import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotSta
import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortOptical;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.types.TableId;
import java.io.IOException;
import java.util.ArrayList;
......@@ -44,24 +41,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
private final AtomicBoolean driverHandshakeComplete;
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private long barrierXidToWaitFor = -1;
private OFPortDescStatsReply wPorts;
OFOpticalSwitchImplLINC13(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
driverHandshakeComplete = new AtomicBoolean(false);
setSwitchDescription(desc);
}
@Override
public String toString() {
return "OFOpticalSwitchImplLINC13 [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
}
@Override
public void startDriverHandshake() {
log.warn("Starting driver handshake for sw {}", getStringId());
......@@ -177,7 +161,7 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
"message " +
"{}",
circuitPortsRequest.toString());
this.write(Collections.<OFMessage>singletonList(circuitPortsRequest));
this.sendMsg(Collections.<OFMessage>singletonList(circuitPortsRequest));
}
@Override
......@@ -190,15 +174,6 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
return Collections.unmodifiableList(portEntries);
}
@Override
public void write(OFMessage msg) {
this.channel.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
this.channel.write(msgs);
}
@Override
public Boolean supportNxRole() {
......@@ -210,15 +185,4 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
return true;
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
......
/*
* Copyright 2014-2015 Open Networking Laboratory
* 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.
......@@ -13,19 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openflow.drivers;
package org.onosproject.driver.handshaker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
......@@ -33,7 +23,6 @@ import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotSta
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
......@@ -66,6 +55,14 @@ import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.util.HexString;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
* Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
......@@ -75,7 +72,7 @@ import org.projectfloodlight.openflow.util.HexString;
public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
private static final int VLAN_ID_OFFSET = 16;
private final AtomicBoolean driverHandshakeComplete;
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private OFFactory factory;
private static final int OFPCML_NO_BUFFER = 0xffff;
// Configuration of asynch messages to controller. We need different
......@@ -106,24 +103,8 @@ public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
private static final short MIN_PRIORITY = 0x0;
private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
private final Map<Integer, OFGroup> l2groups;
public OFSwitchImplCPqD13(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
driverHandshakeComplete = new AtomicBoolean(false);
l2groups = new ConcurrentHashMap<Integer, OFGroup>();
setSwitchDescription(desc);
}
private final Map<Integer, OFGroup> l2groups = new ConcurrentHashMap<>();
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "OFSwitchImplCPqD13 [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((this.getStringId() != null) ? this.getStringId() : "?") + "]]";
}
@Override
public void startDriverHandshake() {
......@@ -1185,7 +1166,7 @@ public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
.setXid(getNextTransactionId())
.build();
write(tableMissEntry);
sendMsg(tableMissEntry);
}
private void sendBarrier(boolean finalBarrier) {
......@@ -1198,34 +1179,11 @@ public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
.setXid(xid)
.build();
write(br);
sendMsg(br);
}
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void write(OFMessage msg) {
this.channel.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
this.channel.write(msgs);
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE; // XXX this needs to be fixed
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
......
......@@ -13,74 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openflow.drivers;
package org.onosproject.driver.handshaker;
import com.google.common.collect.Lists;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
import org.projectfloodlight.openflow.types.TableId;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
//TODO: Knock-off this class as we don't need any switch/app specific
//drivers in the south bound layers.
public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch {
private OFFactory factory;
private final AtomicBoolean driverHandshakeComplete;
private AtomicBoolean haltStateMachine;
/* Default table ID - compatible with CpqD switch */
private static final int TABLE_VLAN = 0;
private static final int TABLE_TMAC = 1;
private static final int TABLE_IPV4_UNICAST = 2;
private static final int TABLE_MPLS = 3;
private static final int TABLE_ACL = 5;
/*
* Set the default values. These variables will get overwritten based on the
* switch vendor type
*/
protected int vlanTableId = TABLE_VLAN;
protected int tmacTableId = TABLE_TMAC;
protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST;
protected int mplsTableId = TABLE_MPLS;
protected int aclTableId = TABLE_ACL;
protected OFSwitchImplSpringOpenTTP(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
driverHandshakeComplete = new AtomicBoolean(false);
haltStateMachine = new AtomicBoolean(false);
setSwitchDescription(desc);
}
@Override
public String toString() {
return "OFSwitchImplSpringOpenTTP ["
+ ((channel != null) ? channel.getRemoteAddress() : "?")
+ " DPID["
+ ((this.getStringId() != null) ? this.getStringId() : "?")
+ "]]";
}
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
@Override
public Boolean supportNxRole() {
return null;
return false;
}
@Override
public void startDriverHandshake() {
log.debug("Starting driver handshake for sw {}", getStringId());
......@@ -103,6 +58,8 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch {
return driverHandshakeComplete.get();
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled) {
......@@ -113,82 +70,4 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch {
}
}
@Override
public void write(OFMessage msg) {
channel.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
channel.write(msgs);
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType type) {
if (msg.getType() == OFType.FLOW_MOD) {
OFFlowMod flowMod = (OFFlowMod) msg;
OFFlowMod.Builder builder = flowMod.createBuilder();
List<OFInstruction> instructions = flowMod.getInstructions();
List<OFInstruction> newInstructions = Lists.newArrayList();
for (OFInstruction i : instructions) {
if (i instanceof OFInstructionGotoTable) {
OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
TableType tid = TableType.values()[gotoTable.getTableId()
.getValue()];
newInstructions.add(gotoTable.createBuilder()
.setTableId(getTableId(tid)).build());
} else {
newInstructions.add(i);
}
}
builder.setTableId(getTableId(type));
builder.setInstructions(newInstructions);
OFMessage msgnew = builder.build();
channel.write(Collections.singletonList(msgnew));
log.trace("Installed {}", msgnew);
} else {
channel.write(Collections.singletonList(msg));
}
}
@Override
public TableType getTableType(TableId tid) {
switch (tid.getValue()) {
case TABLE_IPV4_UNICAST:
return TableType.IP;
case TABLE_MPLS:
return TableType.MPLS;
case TABLE_ACL:
return TableType.ACL;
case TABLE_VLAN:
return TableType.VLAN;
case TABLE_TMAC:
return TableType.ETHER;
default:
log.error("Table type for Table id {} is not supported in the driver",
tid);
return TableType.NONE;
}
}
private TableId getTableId(TableType tableType) {
switch (tableType) {
case IP:
return TableId.of(ipv4UnicastTableId);
case MPLS:
return TableId.of(mplsTableId);
case ACL:
return TableId.of(aclTableId);
case VLAN:
return TableId.of(vlanTableId);
case ETHER:
return TableId.of(tmacTableId);
default: {
log.error("Table type {} is not supported in the driver", tableType);
return TableId.NONE;
}
}
}
}
......
......@@ -15,10 +15,7 @@
*/
package org.onosproject.driver.pipeline;
import com.google.common.util.concurrent.SettableFuture;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
......@@ -84,27 +81,32 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme
treatment = flowTreatment.build();
}
FlowRule rule = new DefaultFlowRule(deviceId, selector,
treatment,
fwd.priority(), fwd.appId(),
new DefaultGroupId(fwd.id()),
fwd.timeout(), fwd.permanent());
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(rule);
flowBuilder.add(ruleBuilder.build());
break;
case REMOVE:
flowBuilder.remove(rule);
flowBuilder.remove(ruleBuilder.build());
break;
default:
log.warn("Unknown operation {}", fwd.op());
}
SettableFuture<Boolean> future = SettableFuture.create();
flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
......
......@@ -18,10 +18,14 @@
<driver name="default" manufacturer="ON.Lab" hwVersion="0.0.1" swVersion="0.0.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.DefaultSwitchHandShaker"/>
</driver>
<driver name="ovs-corsa" manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOVSSwitchCorsaTTP"/>
</driver>
<driver name="spring-open-cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
......@@ -31,4 +35,25 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/>
</driver>
<driver name="cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research"
hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFSwitchImplSpringOpenTTP"/>
</driver>
<driver name="linc-oe" manufacturer="FlowForwarding.org" hwVersion="Unknown"
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/>
</driver>
<driver name="corsa" manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFCorsaSwitchDriver"/>
</driver>
</drivers>
......
......@@ -42,6 +42,11 @@
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -15,12 +15,11 @@
*/
package org.onosproject.openflow.controller;
import java.util.List;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.types.TableId;
import java.util.List;
/**
* Represents to provider facing side of a switch.
......@@ -28,38 +27,6 @@ import org.projectfloodlight.openflow.types.TableId;
public interface OpenFlowSwitch {
/**
* The TableType is used to determine in which table (TableID) each flow rule
* needs to be put for multi-table support switch.
* It is used only for multi-table support switch.
*/
public static enum TableType {
/* VLAN-to-MPLS table */
VLAN_MPLS,
/* VLAN table */
VLAN,
/* Ethertype table */
ETHER,
/* Class of Service table */
COS,
/* IP table */
IP,
/* MPLS table */
MPLS,
/* ACL table */
ACL,
/* Single table */
NONE,
/* First table in multi-table */
FIRST,
}
/**
* Writes the message to the driver.
*
* @param msg the message to write
......@@ -74,17 +41,6 @@ public interface OpenFlowSwitch {
public void sendMsg(List<OFMessage> msgs);
/**
* Transforms FlowMod messages by setting the correct table-ids and sending
* them to the switch. TableType is used to determine the table ID for the OFMessage.
* Switch drivers that supports multi-table pipelines should implement this
* method.
*
* @param msg the message to be written
* @param tableType the type of table in which the FlowMods need to be inserted
*/
public void transformAndSendMsg(OFMessage msg, TableType tableType);
/**
* Handle a message from the switch.
* @param fromSwitch the message to handle
*/
......@@ -192,12 +148,4 @@ public interface OpenFlowSwitch {
* @return string representation of the connection to the device
*/
public String channelId();
/**
* Returns the TableType corresponding to the TableId used to identify
* a table in an OpenFlow switch.
* @param tid identifies a table in an OpenFlow switch using TableId
* @return TableType corresponding to 'tid' identifying the type of table
*/
public TableType getTableType(TableId tid);
}
......
......@@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -27,6 +28,7 @@ import java.util.stream.Collectors;
import org.jboss.netty.channel.Channel;
import org.onlab.packet.IpAddress;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
......@@ -36,10 +38,12 @@ import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFRoleReply;
import org.projectfloodlight.openflow.protocol.OFRoleRequest;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -48,18 +52,19 @@ import org.slf4j.LoggerFactory;
* An abstract representation of an OpenFlow switch. Can be extended by others
* to serve as a base for their vendor specific representation of a switch.
*/
public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
implements OpenFlowSwitchDriver {
protected final Logger log = LoggerFactory.getLogger(getClass());
private static final String SHUTDOWN_MSG = "Worker has already been shutdown";
protected Channel channel;
private Channel channel;
protected String channelId;
private boolean connected;
protected boolean startDriverHandshakeCalled = false;
private final Dpid dpid;
private Dpid dpid;
private OpenFlowAgent agent;
private final AtomicInteger xidCounter = new AtomicInteger(0);
......@@ -76,17 +81,11 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
protected OFFeaturesReply features;
protected OFDescStatsReply desc;
/**
* Given a dpid build this switch.
* @param dp the dpid
*/
protected AbstractOpenFlowSwitch(Dpid dp) {
this.dpid = dp;
}
public AbstractOpenFlowSwitch(Dpid dpid, OFDescStatsReply desc) {
@Override
public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
this.dpid = dpid;
this.desc = desc;
this.ofVersion = ofv;
}
//************************
......@@ -102,7 +101,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
public final void sendMsg(OFMessage m) {
if (role == RoleState.MASTER) {
try {
this.write(m);
channel.write(Collections.singletonList(m));
} catch (RejectedExecutionException e) {
log.warn(e.getMessage());
if (!e.getMessage().contains(SHUTDOWN_MSG)) {
......@@ -116,7 +115,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
public final void sendMsg(List<OFMessage> msgs) {
if (role == RoleState.MASTER) {
try {
this.write(msgs);
channel.write(msgs);
} catch (RejectedExecutionException e) {
log.warn(e.getMessage());
if (!e.getMessage().contains(SHUTDOWN_MSG)) {
......@@ -127,10 +126,15 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
}
@Override
public abstract void write(OFMessage msg);
@Override
public abstract void write(List<OFMessage> msgs);
public final void sendRoleRequest(OFMessage msg) {
if (msg instanceof OFRoleRequest ||
msg instanceof OFNiciraControllerRoleRequest) {
channel.write(Collections.singletonList(msg));
return;
}
throw new IllegalArgumentException("Someone is trying to send " +
"a non role request message");
}
@Override
public final boolean isConnected() {
......@@ -418,11 +422,20 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
return this.desc.getSerialNum();
}
@Override
public boolean isOptical() {
return false;
}
@Override
public String toString() {
return this.getClass().getName() + " [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
}
}
......
......@@ -15,9 +15,9 @@
*/
package org.onosproject.openflow.controller.driver;
import java.util.List;
import org.jboss.netty.channel.Channel;
import org.onosproject.net.driver.HandlerBehaviour;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
......@@ -26,12 +26,14 @@ import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFVersion;
import java.util.List;
/**
* Represents the driver side of an OpenFlow switch.
* This interface should never be exposed to consumers.
*
*/
public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
public interface OpenFlowSwitchDriver extends OpenFlowSwitch, HandlerBehaviour {
/**
* Sets the OpenFlow agent to be used. This method
......@@ -79,23 +81,6 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
public void handleRole(OFMessage m) throws SwitchStateException;
/**
* Starts the driver specific handshake process.
*/
public void startDriverHandshake();
/**
* Checks whether the driver specific handshake is complete.
* @return true is finished, false if not.
*/
public boolean isDriverHandshakeComplete();
/**
* Process a message during the driver specific handshake.
* @param m the message to process.
*/
public void processDriverHandshakeMessage(OFMessage m);
/**
* Announce to the OpenFlow agent that this switch has connected.
* @return true if successful, false if duplicate switch.
*/
......@@ -162,12 +147,6 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
/**
* Does this switch support Nicira Role messages.
* @return true if supports, false otherwise.
*/
public Boolean supportNxRole();
/**
* Sets the OF version for this switch.
* @param ofV the version to set.
*/
......@@ -193,19 +172,42 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
public void setConnected(boolean connected);
/**
* Writes the message to the output stream
* in a driver specific manner.
*
* @param msg the message to write
* Initialises the behaviour.
* @param dpid a dpid
* @param desc a switch description
* @param ofv OpenFlow version
*/
void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv);
/**
* Does this switch support Nicira Role messages.
* @return true if supports, false otherwise.
*/
Boolean supportNxRole();
/**
* Starts the driver specific handshake process.
*/
void startDriverHandshake();
/**
* Checks whether the driver specific handshake is complete.
* @return true is finished, false if not.
*/
boolean isDriverHandshakeComplete();
/**
* Process a message during the driver specific handshake.
* @param m the message to process.
*/
public void write(OFMessage msg);
void processDriverHandshakeMessage(OFMessage m);
/**
* Writes to the OFMessage list to the output stream
* in a driver specific manner.
* Sends only role request messages.
*
* @param msgs the messages to be written
* @param message a role request message.
*/
public void write(List<OFMessage> msgs);
void sendRoleRequest(OFMessage message);
}
......
......@@ -36,11 +36,6 @@
<artifactId>onos-of-api</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-of-drivers</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</dependency>
......
......@@ -21,10 +21,13 @@ import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.onosproject.net.driver.DefaultDriverData;
import org.onosproject.net.driver.DefaultDriverHandler;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.driver.OpenFlowAgent;
import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onosproject.openflow.drivers.DriverManager;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
......@@ -70,6 +73,7 @@ public class Controller {
// Perf. related configuration
protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
private DriverService driverService;
// ***************
// Getters/Setters
......@@ -152,15 +156,7 @@ public class Controller {
if (ofPort != null) {
this.openFlowPort = Integer.parseInt(ofPort);
}
String corsaDpid = configParams.get("corsaDpid");
if (corsaDpid != null) {
try {
DriverManager.setCorsaDpid(new Dpid(corsaDpid));
log.info("Corsa DPID set to {}", corsaDpid);
} catch (NumberFormatException e) {
log.warn("Malformed Corsa DPID string", e);
}
}
log.debug("OpenFlow port set to {}", this.openFlowPort);
String threads = configParams.get("workerthreads");
this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
......@@ -206,17 +202,28 @@ public class Controller {
* @return switch instance
*/
protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
OFDescStatsReply desc, OFVersion ofv) {
OpenFlowSwitchDriver sw = DriverManager.getSwitch(new Dpid(dpid),
desc, ofv);
sw.setAgent(agent);
sw.setRoleHandler(new RoleManager(sw));
return sw;
OFDescStatsReply desc,
OFVersion ofv) {
Driver driver = driverService
.getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc());
if (driver.hasBehaviour(OpenFlowSwitchDriver.class)) {
OpenFlowSwitchDriver ofSwitchDriver = driver.createBehaviour(new DefaultDriverHandler(
new DefaultDriverData(driver)), OpenFlowSwitchDriver.class);
ofSwitchDriver.init(new Dpid(dpid), desc, ofv);
ofSwitchDriver.setAgent(agent);
ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver));
return ofSwitchDriver;
}
log.error("No OpenFlow driver for {} : {}", dpid, desc);
return null;
}
public void start(OpenFlowAgent ag) {
public void start(OpenFlowAgent ag, DriverService driverService) {
log.info("Starting OpenFlow IO");
this.agent = ag;
this.driverService = driverService;
this.init();
this.run();
}
......
......@@ -23,7 +23,10 @@ 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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.net.driver.DriverService;
import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.OpenFlowController;
......@@ -76,6 +79,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
private static final Logger log =
LoggerFactory.getLogger(OpenFlowControllerImpl.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
private final ExecutorService executorMsgs =
Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
......@@ -115,7 +121,7 @@ public class OpenFlowControllerImpl implements OpenFlowController {
public void activate(ComponentContext context) {
Map<String, String> properties = readComponentConfiguration(context);
ctrl.setConfigParams(properties);
ctrl.start(agent);
ctrl.start(agent, driverService);
}
@Deactivate
......
......@@ -15,10 +15,8 @@
*/
package org.onosproject.openflow.controller.impl;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onosproject.openflow.controller.driver.RoleHandler;
......@@ -30,7 +28,6 @@ import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFExperimenter;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
import org.projectfloodlight.openflow.protocol.OFRoleReply;
......@@ -42,8 +39,8 @@ import org.projectfloodlight.openflow.types.U64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
......@@ -103,7 +100,7 @@ class RoleManager implements RoleHandler {
.setXid(xid)
.setRole(roleToSend)
.build();
sw.write(Collections.<OFMessage>singletonList(roleRequest));
sw.sendRoleRequest(roleRequest);
return xid;
}
......@@ -133,7 +130,8 @@ class RoleManager implements RoleHandler {
//FIXME fix below when we actually use generation ids
.setGenerationId(U64.ZERO)
.build();
sw.write(rrm);
sw.sendRoleRequest(rrm);
return xid;
}
......
......@@ -15,15 +15,14 @@
*/
package org.onosproject.openflow.controller.impl;
import java.io.IOException;
import java.util.List;
import org.jboss.netty.channel.Channel;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.net.driver.DriverData;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
import org.onosproject.openflow.controller.driver.OpenFlowAgent;
import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onosproject.openflow.controller.driver.RoleHandler;
......@@ -39,12 +38,16 @@ import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U64;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.onosproject.openflow.controller.RoleState.*;
import static org.onosproject.openflow.controller.driver.RoleRecvStatus.*;
import static org.onosproject.openflow.controller.RoleState.MASTER;
import static org.onosproject.openflow.controller.RoleState.SLAVE;
import static org.onosproject.openflow.controller.driver.RoleRecvStatus.MATCHED_CURRENT_ROLE;
import static org.onosproject.openflow.controller.driver.RoleRecvStatus.OTHER_EXPECTATION;
public class RoleManagerTest {
......@@ -112,9 +115,6 @@ public class RoleManagerTest {
public void sendMsg(List<OFMessage> msgs) {
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
}
@Override
public void handleMessage(OFMessage fromSwitch) {
......@@ -224,6 +224,11 @@ public class RoleManagerTest {
}
@Override
public void sendRoleRequest(OFMessage message) {
}
@Override
public boolean connectSwitch() {
return false;
}
......@@ -293,16 +298,13 @@ public class RoleManagerTest {
}
@Override
public boolean isConnected() {
return false;
}
public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
@Override
public void write(OFMessage msg) {
}
@Override
public void write(List<OFMessage> msgs) {
public boolean isConnected() {
return false;
}
@Override
......@@ -316,9 +318,23 @@ public class RoleManagerTest {
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
public DriverHandler handler() {
return null;
}
@Override
public void setHandler(DriverHandler handler) {
}
@Override
public DriverData data() {
return null;
}
@Override
public void setData(DriverData data) {
}
}
}
......
<!--
~ 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-of</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-of-drivers</artifactId>
<packaging>bundle</packaging>
<description>ONOS OpenFlow switch drivers &amp; factory</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-of-api</artifactId>
</dependency>
</dependencies>
</project>
/*
* Copyright 2014-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.openflow.drivers;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriverFactory;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.TableId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* A simple implementation of a driver manager that differentiates between
* connected switches using the OF Description Statistics Reply message.
*/
public final class DriverManager implements OpenFlowSwitchDriverFactory {
private static final Logger log = LoggerFactory.getLogger(DriverManager.class);
private static final int LOWEST_PRIORITY = 0;
private static Dpid corsaDpid = new Dpid();
/**
* Return an IOFSwitch object based on switch's manufacturer description
* from OFDescStatsReply.
*
* @param desc DescriptionStatistics reply from the switch
* @return A IOFSwitch instance if the driver found an implementation for
* the given description. Otherwise it returns OFSwitchImplBase
*/
@Override
public OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
OFDescStatsReply desc, OFVersion ofv) {
String vendor = desc.getMfrDesc();
String hw = desc.getHwDesc();
String sw = desc.getSwDesc();
if (dpid.equals(corsaDpid)) {
if (hw.startsWith("Open vSwitch")) {
return new OFOVSSwitchCorsaTTP(dpid, desc);
} else {
return new OFCorsaSwitchDriver(dpid, desc);
}
}
if (vendor.startsWith("Stanford University, Ericsson Research and CPqD Research")
&&
hw.startsWith("OpenFlow 1.3 Reference Userspace Switch")) {
return new OFSwitchImplSpringOpenTTP(dpid, desc);
}
//TODO: Temporary work around until the configuration based
// driver manager framework is ready
if (vendor.contains("Dell")
&&
hw.contains("OpenFlow switch HW ver. 1.0")) {
return new OFSwitchImplSpringOpenTTPDellOSR(dpid, desc);
}
if (hw.startsWith("Open vSwitch")) {
if (ofv == OFVersion.OF_10) {
return new OFSwitchImplOVS10(dpid, desc);
} else if (ofv == OFVersion.OF_13) {
return new OFSwitchImplOVS13(dpid, desc);
}
}
if (vendor.equals("Pica8, Inc.") && sw.startsWith("PicOS") &&
ofv == OFVersion.OF_13) {
return new OFSwitchImplOVS13(dpid, desc);
}
if (sw.startsWith("LINC-OE")) {
log.warn("Optical Emulator LINC-OE with DPID:{} found..", dpid);
return new OFOpticalSwitchImplLINC13(dpid, desc);
}
if (vendor.startsWith("Corsa") && hw.startsWith("Corsa Element")
&& sw.startsWith("2.3.1")) {
log.warn("Corsa Switch 2.3.1 found");
return new OFCorsaSwitchDriver(dpid, desc);
}
log.warn("DriverManager could not identify switch desc: {}. "
+ "Assigning AbstractOpenFlowSwich", desc);
return new AbstractOpenFlowSwitch(dpid, desc) {
@Override
public void setRole(RoleState state) {
this.role = RoleState.MASTER;
}
@Override
public void write(List<OFMessage> msgs) {
channel.write(msgs);
}
@Override
public void write(OFMessage msg) {
channel.write(Collections.singletonList(msg));
}
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void startDriverHandshake() {
if (factory().getVersion() == OFVersion.OF_10) {
OFFlowAdd.Builder fmBuilder = factory().buildFlowAdd();
fmBuilder.setPriority(LOWEST_PRIORITY);
write(fmBuilder.build());
}
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {}
@Override
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public List<OFPortDesc> getPorts() {
if (this.factory().getVersion() == OFVersion.OF_10) {
return Collections.unmodifiableList(features.getPorts());
} else {
return Collections.unmodifiableList(this.ports.stream()
.flatMap((portReply) -> (portReply.getEntries().stream()))
.collect(Collectors.toList()));
}
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
};
}
/**
* Private constructor to avoid instantiation.
*/
private DriverManager() {
}
public static OpenFlowSwitchDriver getSwitch(Dpid dpid,
OFDescStatsReply desc, OFVersion ofv) {
return new DriverManager().getOFSwitchImpl(dpid, desc, ofv);
}
public static void setCorsaDpid(Dpid dpid) {
corsaDpid = dpid;
}
}
/*
* 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.openflow.drivers;
import org.onosproject.openflow.controller.Dpid;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
/*import com.google.common.collect.Lists;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
import org.projectfloodlight.openflow.types.TableId;
import java.util.List;
*/
import java.util.Collections;
public class OFOVSSwitchCorsaTTP extends OFCorsaSwitchDriver {
OFOVSSwitchCorsaTTP(Dpid dpid, OFDescStatsReply desc) {
super(dpid, desc);
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType type) {
/*log.trace("Trying to send {} of TableType {}", msg, type);
if (msg.getType() == OFType.FLOW_MOD) {
OFFlowMod flowMod = (OFFlowMod) msg;
OFFlowMod.Builder builder = flowMod.createBuilder();
List<OFInstruction> instructions = flowMod.getInstructions();
List<OFInstruction> newInstructions = Lists.newArrayList();
for (OFInstruction i : instructions) {
if (i instanceof OFInstructionGotoTable) {
OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
switch (tid) {
case VLAN_MPLS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
break;
case VLAN:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(VLAN_TABLE)).build());
break;
case ETHER:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(ETHER_TABLE)).build());
break;
case COS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(COS_MAP_TABLE)).build());
break;
case IP:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(FIB_TABLE)).build());
break;
case MPLS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(MPLS_TABLE)).build());
break;
case ACL:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(LOCAL_TABLE)).build());
break;
case NONE:
log.error("Should never have to go to Table 0");
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(0)).build());
break;
default:
log.warn("Unknown table type: {}", tid);
}
} else {
newInstructions.add(i);
}
}
switch (type) {
case VLAN_MPLS:
builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
break;
case VLAN:
builder.setTableId(TableId.of(VLAN_TABLE));
break;
case ETHER:
builder.setTableId(TableId.of(ETHER_TABLE));
break;
case COS:
builder.setTableId(TableId.of(COS_MAP_TABLE));
break;
case IP:
builder.setTableId(TableId.of(FIB_TABLE));
break;
case MPLS:
builder.setTableId(TableId.of(MPLS_TABLE));
break;
case ACL:
builder.setTableId(TableId.of(LOCAL_TABLE));
break;
case FIRST:
builder.setTableId(TableId.of(FIRST_TABLE));
break;
case NONE:
builder.setTableId(TableId.of(LOCAL_TABLE));
break;
default:
log.warn("Unknown table type: {}", type);
}
builder.setInstructions(newInstructions);
OFMessage msgnew = builder.build();
channel.write(Collections.singletonList(msgnew));
log.debug("Installed {}", msgnew);
} else {
channel.write(Collections.singletonList(msg));
}*/
channel.write(Collections.singletonList(msg));
}
}
/*
* Copyright 2014-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.openflow.drivers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Nicira, Inc. Make
* (Hardware Desc.) : Open vSwitch Model (Datapath Desc.) : None Software :
* 2.1.0 (or whatever version + build) Serial : None
*/
public class OFSwitchImplOVS13 extends AbstractOpenFlowSwitch {
private final AtomicBoolean driverHandshakeComplete;
private OFFactory factory;
private long barrierXidToWaitFor = -1;
private static final short MIN_PRIORITY = 0x0;
private static final int OFPCML_NO_BUFFER = 0xffff;
public OFSwitchImplOVS13(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
driverHandshakeComplete = new AtomicBoolean(false);
setSwitchDescription(desc);
}
@Override
public String toString() {
return "OFSwitchImplOVS13 [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
}
@Override
public void startDriverHandshake() {
log.debug("Starting driver handshake for sw {}", getStringId());
if (startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeAlreadyStarted();
}
startDriverHandshakeCalled = true;
factory = factory();
configureSwitch();
}
@Override
public boolean isDriverHandshakeComplete() {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
return driverHandshakeComplete.get();
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
if (driverHandshakeComplete.get()) {
throw new SwitchDriverSubHandshakeCompleted(m);
}
switch (m.getType()) {
case BARRIER_REPLY:
if (m.getXid() == barrierXidToWaitFor) {
driverHandshakeComplete.set(true);
}
break;
case ERROR:
log.error("Switch {} Error {}", getStringId(), m);
break;
case FEATURES_REPLY:
break;
case FLOW_REMOVED:
break;
case GET_ASYNC_REPLY:
// OFAsyncGetReply asrep = (OFAsyncGetReply)m;
// decodeAsyncGetReply(asrep);
break;
case PACKET_IN:
break;
case PORT_STATUS:
break;
case QUEUE_GET_CONFIG_REPLY:
break;
case ROLE_REPLY:
break;
case STATS_REPLY:
// processStatsReply((OFStatsReply) m);
break;
default:
log.debug("Received message {} during switch-driver subhandshake "
+ "from switch {} ... Ignoring message", m, getStringId());
}
}
private void configureSwitch() {
sendBarrier(true);
}
private void sendBarrier(boolean finalBarrier) {
int xid = getNextTransactionId();
if (finalBarrier) {
barrierXidToWaitFor = xid;
}
OFBarrierRequest br = factory
.buildBarrierRequest()
.setXid(xid)
.build();
write(br);
}
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void write(OFMessage msg) {
channel.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
channel.write(msgs);
}
/**
* By default if none of the booleans in the call are set, then the
* table-miss entry is added with no instructions, which means that pipeline
* execution will stop, and the action set associated with the packet will
* be executed.
*
* @param tableToAdd
* @param toControllerNow as an APPLY_ACTION instruction
* @param toControllerWrite as a WRITE_ACITION instruction
* @param toTable as a GOTO_TABLE instruction
* @param tableToSend
*/
@SuppressWarnings("unchecked")
private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
boolean toControllerWrite,
boolean toTable, int tableToSend) {
OFOxmList oxmList = OFOxmList.EMPTY;
OFMatchV3 match = factory.buildMatchV3()
.setOxmList(oxmList)
.build();
OFAction outc = factory.actions()
.buildOutput()
.setPort(OFPort.CONTROLLER)
.setMaxLen(OFPCML_NO_BUFFER)
.build();
List<OFInstruction> instructions = new ArrayList<OFInstruction>();
if (toControllerNow) {
// table-miss instruction to send to controller immediately
OFInstruction instr = factory.instructions()
.buildApplyActions()
.setActions(Collections.singletonList(outc))
.build();
instructions.add(instr);
}
if (toControllerWrite) {
// table-miss instruction to write-action to send to controller
// this will be executed whenever the action-set gets executed
OFInstruction instr = factory.instructions()
.buildWriteActions()
.setActions(Collections.singletonList(outc))
.build();
instructions.add(instr);
}
if (toTable) {
// table-miss instruction to goto-table x
OFInstruction instr = factory.instructions()
.gotoTable(TableId.of(tableToSend));
instructions.add(instr);
}
if (!toControllerNow && !toControllerWrite && !toTable) {
// table-miss has no instruction - at which point action-set will be
// executed - if there is an action to output/group in the action
// set
// the packet will be sent there, otherwise it will be dropped.
instructions = Collections.EMPTY_LIST;
}
OFMessage tableMissEntry = factory.buildFlowAdd()
.setTableId(TableId.of(tableToAdd))
.setMatch(match) // match everything
.setInstructions(instructions)
.setPriority(MIN_PRIORITY)
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
.setXid(getNextTransactionId())
.build();
write(tableMissEntry);
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
......@@ -34,7 +34,6 @@
<modules>
<module>api</module>
<module>ctl</module>
<module>drivers</module>
</modules>
<dependencies>
......
......@@ -21,7 +21,6 @@
<feature>onos-api</feature>
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
<bundle>mvn:${project.groupId}/onos-of-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-of-drivers/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-of-ctl/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-lldp-provider/${project.version}</bundle>
......
......@@ -15,21 +15,9 @@
*/
package org.onosproject.provider.of.device.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.Device.Type.*;
import static org.onosproject.net.MastershipRole.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -51,7 +39,6 @@ import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.PacketListener;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
......@@ -59,11 +46,18 @@ import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.*;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.net.MastershipRole.*;
public class OpenFlowDeviceProviderTest {
......@@ -400,17 +394,6 @@ public class OpenFlowDeviceProviderTest {
return "1.2.3.4:1";
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
}
......
package org.onosproject.provider.of.group.impl;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -42,15 +41,12 @@ import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.errormsg.OFGroupModFailedErrorMsg;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.TableId;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.*;
public class OpenFlowGroupProviderTest {
......@@ -396,14 +392,5 @@ public class OpenFlowGroupProviderTest {
return null;
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
}
\ No newline at end of file
......
......@@ -15,18 +15,13 @@
*/
package org.onosproject.provider.of.packet.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
......@@ -49,9 +44,6 @@ import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.PacketListener;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
......@@ -61,10 +53,13 @@ import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.*;
public class OpenFlowPacketProviderTest {
......@@ -430,16 +425,6 @@ public class OpenFlowPacketProviderTest {
return "1.2.3.4:1";
}
@Override
public TableType getTableType(TableId tid) {
return TableType.NONE;
}
@Override
public void transformAndSendMsg(OFMessage msg, TableType tableType) {
// TODO Auto-generated method stub
}
}
......