alshabib

switch can now connect

......@@ -13,7 +13,7 @@ public interface OpenFlowSwitch {
*
* @param msg the message to write
*/
public void write(OFMessage msg);
public void sendMsg(OFMessage msg);
/**
* Handle a message from the switch.
......
......@@ -18,7 +18,9 @@
package org.onlab.onos.of.controller.impl.internal;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.netty.channel.Channel;
import org.onlab.onos.of.controller.Dpid;
......@@ -27,12 +29,14 @@ import org.onlab.onos.of.controller.RoleState;
import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFExperimenter;
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.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFRoleReply;
import org.projectfloodlight.openflow.protocol.OFVersion;
......@@ -45,10 +49,13 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
private static Logger log =
LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
private Channel channel;
protected Channel channel;
protected boolean startDriverHandshakeCalled = false;
private boolean connected;
private Dpid dpid;
private OpenFlowSwitchAgent agent;
private AtomicInteger xidCounter = new AtomicInteger(0);
private OFVersion ofVersion;
......@@ -58,8 +65,12 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
private final RoleManager roleMan = new RoleManager(this);
protected AbstractOpenFlowSwitch(long dpid) {
this.dpid = new Dpid(dpid);
protected RoleState role;
protected OFFeaturesReply features;
protected AbstractOpenFlowSwitch(Dpid dp) {
this.dpid = dp;
}
//************************
......@@ -80,14 +91,16 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
*
* @param m the message to be written
*/
public abstract void write(OFMessage m);
public abstract void sendMsg(OFMessage m);
/**
* Writes to the OFMessage list to the output stream.
*
* @param msgs the messages to be written
*/
public abstract void write(List<OFMessage> msgs);
public void write(List<OFMessage> msgs) {
this.channel.write(msgs);
}
/**
......@@ -151,7 +164,9 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
this.tableFull = full;
}
public abstract void setFeaturesReply(OFFeaturesReply featuresReply);
public void setFeaturesReply(OFFeaturesReply featuresReply) {
this.features = featuresReply;
}
/**
* Let peoeple know if you support Nicira style role requests.
......@@ -172,7 +187,9 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
this.agent.processMessage(m);
}
public abstract RoleState getRole();
public RoleState getRole() {
return role;
};
final boolean addConnectedSwitch() {
return this.agent.addConnectedSwitch(this.getId(), this);
......@@ -214,7 +231,9 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
public void setRole(RoleState role) {
try {
this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
this.role = role;
}
} catch (IOException e) {
log.error("Unable to write to switch {}.", this.dpid);
}
......@@ -236,20 +255,20 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
}
void handleNiciraRole(OFMessage m) throws SwitchStateException {
RoleState role = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
if (role == null) {
RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
if (r == null) {
// The message wasn't really a Nicira role reply. We just
// dispatch it to the OFMessage listeners in this case.
this.handleMessage(m);
}
RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
new RoleReplyInfo(role, null, m.getXid()));
new RoleReplyInfo(r, null, m.getXid()));
if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
if (role == RoleState.MASTER) {
if (r == RoleState.MASTER) {
this.transitionToMasterSwitch();
} else if (role == RoleState.EQUAL ||
role == RoleState.SLAVE) {
} else if (r == RoleState.EQUAL ||
r == RoleState.SLAVE) {
this.transitionToEqualSwitch();
}
}
......@@ -274,6 +293,16 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
this.agent = ag;
}
public void setSwitchDescription(OFDescStatsReply desc) {
// TODO Auto-generated method stub
}
protected int getNextTransactionId() {
return this.xidCounter.getAndIncrement();
}
protected List<OFPortDesc> getPorts() {
return Collections.unmodifiableList(ports.getEntries());
}
}
......
......@@ -29,9 +29,11 @@ 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.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
import org.onlab.onos.of.drivers.DriverManager;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
......@@ -83,11 +85,6 @@ public class Controller {
// Getters/Setters
// ***************
public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
this.switchManager = swManager;
}
public OFFactory getOFMessageFactory10() {
return FACTORY10;
}
......@@ -201,18 +198,6 @@ public class Controller {
}
/**
* Startup all of the controller's components.
*/
@LogMessageDoc(message = "Waiting for storage source",
explanation = "The system database is not yet ready",
recommendation = "If this message persists, this indicates " +
"that the system database has failed to start. " +
LogMessageDoc.CHECK_CONTROLLER)
public synchronized void startupComponents() {
//TODO do something maybe
}
// **************
// Utility methods
// **************
......@@ -236,9 +221,10 @@ public class Controller {
* @param desc
* @return switch instance
*/
protected AbstractOpenFlowSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
AbstractOpenFlowSwitch sw = switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
desc.getSwDesc(), ofv);
protected AbstractOpenFlowSwitch getOFSwitchInstance(long dpid,
OFDescStatsReply desc, OFVersion ofv) {
AbstractOpenFlowSwitch sw = DriverManager.getOFSwitchImpl(new Dpid(dpid),
desc, ofv);
sw.setAgent(agent);
return sw;
}
......@@ -247,7 +233,6 @@ public class Controller {
log.info("Initialising OpenFlow Lib and IO");
this.agent = ag;
this.init(new HashMap<String, String>());
this.startupComponents();
this.run();
}
......
......@@ -230,12 +230,6 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
h.thisdpid = m.getDatapathId().getLong();
log.info("Received features reply for switch at {} with dpid {}",
h.getSwitchInfoString(), h.thisdpid);
//update the controller about this connected switch
boolean success = h.sw.addConnectedSwitch();
if (!success) {
disconnectDuplicate(h);
return;
}
h.featuresReply = m; //temp store
if (h.ofVersion == OFVersion.OF_10) {
......@@ -419,7 +413,12 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
h.channel.getRemoteAddress());
OFDescStatsReply drep = (OFDescStatsReply) m;
// Here is where we differentiate between different kinds of switches
h.sw = h.controller.getOFSwitchInstance(drep, h.ofVersion);
h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion);
boolean success = h.sw.addConnectedSwitch();
if (!success) {
disconnectDuplicate(h);
return;
}
// set switch information
h.sw.setOFVersion(h.ofVersion);
h.sw.setFeaturesReply(h.featuresReply);
......@@ -433,7 +432,9 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
//Put switch in EQUAL mode until we hear back from the global registry
log.debug("Setting new switch {} to EQUAL and sending Role request",
h.sw.getStringId());
h.setSwitchRole(RoleState.EQUAL);
h.sw.addActivatedEqualSwitch();
//h.setSwitchRole(RoleState.EQUAL);
h.setSwitchRole(RoleState.MASTER);
h.sw.startDriverHandshake();
h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
......
......@@ -24,12 +24,19 @@ import org.slf4j.LoggerFactory;
@Service
public class OpenFlowControllerImpl implements OpenFlowController {
protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
private static final Logger log =
LoggerFactory.getLogger(OpenFlowControllerImpl.class);
protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches =
new ConcurrentHashMap<Long, OpenFlowSwitch>();
protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches =
new ConcurrentHashMap<Long, OpenFlowSwitch>();
protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches =
new ConcurrentHashMap<Long, OpenFlowSwitch>();
protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
protected ArrayList<OpenFlowSwitchListener> ofEventListener;
protected ArrayList<OpenFlowSwitchListener> ofEventListener =
new ArrayList<OpenFlowSwitchListener>();
private final Controller ctrl = new Controller();
......@@ -98,29 +105,17 @@ public class OpenFlowControllerImpl implements OpenFlowController {
@Override
public void write(Dpid dpid, OFMessage msg) {
this.getSwitch(dpid).write(msg);
this.getSwitch(dpid).sendMsg(msg);
}
@Override
public void processPacket(OFMessage msg) {
log.info("Got message {}", msg);
}
@Override
public void setRole(Dpid dpid, RoleState role) {
switch (role) {
case MASTER:
agent.transitionToMasterSwitch(dpid.value());
break;
case EQUAL:
agent.transitionToEqualSwitch(dpid.value());
break;
case SLAVE:
//agent.transitionToSlaveSwitch(dpid.value());
break;
default:
//WTF role is this?
}
((AbstractOpenFlowSwitch) getSwitch(dpid)).setRole(role);
}
public class OpenFlowSwitchAgent {
......@@ -189,6 +184,7 @@ public class OpenFlowControllerImpl implements OpenFlowController {
return false;
}
activeEqualSwitches.put(dpid, sw);
log.info("Added Activated EQUAL Switch {}", dpid);
return true;
} finally {
switchLock.unlock();
......@@ -203,6 +199,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
protected void transitionToMasterSwitch(long dpid) {
switchLock.lock();
try {
if (activeMasterSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
if (sw == null) {
log.error("Transition to master called on sw {}, but switch "
......@@ -224,6 +223,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
protected void transitionToEqualSwitch(long dpid) {
switchLock.lock();
try {
if (activeEqualSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
log.error("Transition to equal called on sw {}, but switch "
......
......@@ -2,7 +2,6 @@ package org.onlab.onos.of.controller.impl.internal;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import org.onlab.onos.of.controller.RoleState;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
......@@ -50,7 +49,6 @@ class RoleManager {
// the expectation set by the caller for the returned role
private RoleRecvStatus expectation;
private AtomicInteger xidCounter;
private AbstractOpenFlowSwitch sw;
......@@ -58,7 +56,6 @@ class RoleManager {
this.requestPending = false;
this.pendingXid = -1;
this.pendingRole = null;
this.xidCounter = new AtomicInteger(0);
this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
this.sw = sw;
}
......@@ -85,7 +82,7 @@ class RoleManager {
roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
}
int xid = xidCounter.getAndIncrement();
int xid = sw.getNextTransactionId();
OFExperimenter roleRequest = OFFactories.getFactory(OFVersion.OF_10)
.buildNiciraControllerRoleRequest()
.setXid(xid)
......@@ -113,7 +110,7 @@ class RoleManager {
+ " Should only be used for queries.", sw);
}
int xid = xidCounter.getAndIncrement();
int xid = sw.getNextTransactionId();
OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13)
.buildRoleRequest()
.setRole(roleToSend)
......@@ -121,7 +118,7 @@ class RoleManager {
//FIXME fix below when we actually use generation ids
.setGenerationId(U64.ZERO)
.build();
sw.write(rrm);
sw.sendMsg(rrm);
return xid;
}
......
package org.onlab.onos.of.drivers;
import java.util.List;
import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.RoleState;
import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A simple implementation of a driver manager that differentiates between
* connected switches using the OF Description Statistics Reply message.
*/
public final class DriverManager {
private static final Logger log = LoggerFactory.getLogger(DriverManager.class);
// Whether to use an OF 1.3 configured TTP, or to use an OF 1.0-style
// single table with packet-ins.
private static boolean cpqdUsePipeline13 = false;
/**
* 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
*/
public static AbstractOpenFlowSwitch getOFSwitchImpl(Dpid dpid,
OFDescStatsReply desc, OFVersion ofv) {
String vendor = desc.getMfrDesc();
String hw = desc.getHwDesc();
if (vendor.startsWith("Stanford University, Ericsson Research and CPqD Research")
&&
hw.startsWith("OpenFlow 1.3 Reference Userspace Switch")) {
return new OFSwitchImplCPqD13(dpid, desc, cpqdUsePipeline13);
}
if (vendor.startsWith("Nicira") &&
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);
}
}
log.warn("DriverManager could not identify switch desc: {}. "
+ "Assigning OFSwitchImplBase", desc);
AbstractOpenFlowSwitch base = new AbstractOpenFlowSwitch(dpid) {
@Override
public void write(List<OFMessage> msgs) {
// TODO Auto-generated method stub
}
@Override
public void sendMsg(OFMessage m) {
// TODO Auto-generated method stub
}
@Override
public Boolean supportNxRole() {
// TODO Auto-generated method stub
return null;
}
@Override
public void startDriverHandshake() {
// TODO Auto-generated method stub
}
@Override
public void setFeaturesReply(OFFeaturesReply featuresReply) {
// TODO Auto-generated method stub
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
// TODO Auto-generated method stub
}
@Override
public boolean isDriverHandshakeComplete() {
// TODO Auto-generated method stub
return false;
}
@Override
public RoleState getRole() {
// TODO Auto-generated method stub
return null;
}
};
base.setSwitchDescription(desc);
// XXX S must set counter here - unidentified switch
return base;
}
/**
* Private constructor to avoid instantiation.
*/
private DriverManager() {
}
/**
* Sets the configuration parameter which determines how the CPqD switch
* is set up. If usePipeline13 is true, a 1.3 pipeline will be set up on
* the switch. Otherwise, the switch will be set up in a 1.0 style with
* a single table where missed packets are sent to the controller.
*
* @param usePipeline13 whether to use a 1.3 pipeline or not
*/
public static void setConfigForCpqd(boolean usePipeline13) {
cpqdUsePipeline13 = usePipeline13;
}
}
package org.onlab.onos.of.drivers;
import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
/**
* 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
*/
public class OFSwitchImplOVS10 extends AbstractOpenFlowSwitch {
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 void sendMsg(OFMessage m) {
channel.write(m);
}
@Override
public Boolean supportNxRole() {
return true;
}
@Override
public void startDriverHandshake() {}
@Override
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {}
}
package org.onlab.onos.of.drivers;
import java.util.concurrent.atomic.AtomicBoolean;
import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 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 static Logger log =
LoggerFactory.getLogger(OFSwitchImplOVS13.class);
private AtomicBoolean driverHandshakeComplete;
private OFFactory factory;
private long barrierXidToWaitFor = -1;
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(), (OFErrorMsg) 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();
sendMsg(br);
}
@Override
public void sendMsg(OFMessage m) {
channel.write(m);
}
@Override
public Boolean supportNxRole() {
return false;
}
}