blob: 1f366150532836c29750a56458f80805edaebec3 [file] [log] [blame]
package net.onrc.onos.ofcontroller.core.internal;
import java.util.ArrayList;
import java.util.List;
import net.floodlightcontroller.routing.Link;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.ofcontroller.core.ILinkStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
import net.onrc.onos.graph.GraphDBManager;
/**
* This is the class for storing the information of links into GraphDB
*/
public class LinkStorageImpl implements ILinkStorage {
protected final static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
protected DBOperation dbop;
private static PerfMon pm = PerfMon.getInstance();
/**
* Initialize the object. Open LinkStorage using given configuration file.
* @param conf Path (absolute path for now) to configuration file.
*/
@Override
public void init(final String dbStore, final String conf) {
//this.dbop = GraphDBManager.getDBOperation(dbStore, conf);
this.dbop = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
}
// Method designing policy:
// op.commit() and op.rollback() MUST called in public (first-class) methods.
// A first-class method MUST NOT call other first-class method.
// Routine process should be implemented in private method.
// A private method MUST NOT call commit or rollback.
/**
* Update a record in the LinkStorage in a way provided by dmop.
* @param link Record of a link to be updated.
* @param linkinfo Meta-information of a link to be updated.
* @param dmop Operation to be done.
*/
@Override
public boolean update(Link link, LinkInfo linkinfo, DM_OPERATION dmop) {
boolean success = false;
switch (dmop) {
case CREATE:
case INSERT:
if (link != null) {
try {
if (addLinkImpl(link)) {
dbop.commit();
success = true;
}
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
}
}
break;
case UPDATE:
if (link != null && linkinfo != null) {
try {
if (setLinkInfoImpl(link, linkinfo)) {
dbop.commit();
success = true;
}
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
}
}
break;
case DELETE:
if (link != null) {
try {
if (deleteLinkImpl(link)) {
dbop.commit();
success = true;
log.debug("LinkStorageImpl:update {} link:{} succeeded", dmop, link);
} else {
dbop.rollback();
log.debug("LinkStorageImpl:update {} link:{} failed", dmop, link);
}
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
}
}
break;
}
return success;
}
@Override
public boolean addLink(Link link) {
return addLink(link, null);
}
private void deleteDeviceOnPort(Long dpid, Short number)
{
IPortObject srcPortObject = dbop.searchPort(HexString.toHexString(dpid), number);
if (srcPortObject == null)
return;
Iterable<IDeviceObject> devices = srcPortObject.getDevices();
if (devices == null)
return;
if (devices.iterator().hasNext()) {
for (IDeviceObject deviceObject: srcPortObject.getDevices()) {
srcPortObject.removeDevice(deviceObject);
log.debug("delete Device "+ deviceObject.getMACAddress() +
" from sw: {} port: {} due to a new link added",
dpid, number);
}
}
}
@Override
public boolean addLink(Link link, LinkInfo linfo) {
boolean success = false;
try {
//delete the Device attachment points for the related switch and port
deleteDeviceOnPort(link.getSrc(),link.getSrcPort());
deleteDeviceOnPort(link.getDst(),link.getDstPort());
long startLinkTime = System.nanoTime();
pm.addlink_start();
if (addLinkImpl(link)) {
// Set LinkInfo only if linfo is non-null.
if (linfo != null && (! setLinkInfoImpl(link, linfo))) {
log.debug("Adding linkinfo failed: {}", link);
dbop.rollback();
}
dbop.commit();
pm.addlink_end();
long endLinkTime = System.nanoTime();
log.error("Performance ##add link total time {}", endLinkTime - startLinkTime);
success = true;
} else {
pm.addlink_end();
// If we fail here that's because the ports aren't added
// before we try to add the link
log.debug("Adding link failed: {}", link);
dbop.rollback();
}
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:addLink link:{} linfo:{} failed", link, linfo);
}
return success;
}
/**
* Update multiple records in the LinkStorage in a way provided by op.
* @param links List of records to be updated.
* @param op Operation to be done.
*/
@Override
public boolean addLinks(List<Link> links) {
boolean success = false;
for (Link lt: links) {
if (! addLinkImpl(lt)) {
return false;
}
}
try {
dbop.commit();
success = true;
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:addLinks link:s{} failed", links);
}
return success;
}
/**
* Delete a record in the LinkStorage.
* @param lt Record to be deleted.
*/
@Override
public boolean deleteLink(Link lt) {
boolean success = false;
log.debug("LinkStorageImpl:deleteLink(): {}", lt);
try {
if (deleteLinkImpl(lt)) {
dbop.commit();
success = true;
log.debug("LinkStorageImpl:deleteLink(): deleted edges {}", lt);
} else {
dbop.rollback();
log.error("LinkStorageImpl:deleteLink(): failed invalid vertices {}", lt);
}
} catch (Exception e) {
dbop.rollback();
log.error("LinkStorageImpl:deleteLink(): failed {} {}",
new Object[]{lt, e.toString()});
e.printStackTrace();
}
return success;
}
/**
* Delete multiple records in LinkStorage.
* @param links List of records to be deleted.
*/
@Override
public boolean deleteLinks(List<Link> links) {
boolean success = false;
try {
for (Link lt : links) {
if (! deleteLinkImpl(lt)) {
dbop.rollback();
return false;
}
}
dbop.commit();
success = true;
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:deleteLinks failed invalid vertices {}", links);
}
return success;
}
/**
* Get list of all links connected to the port specified by given DPID and port number.
* @param dpid DPID of desired port.
* @param port Port number of desired port.
* @return List of links. Empty list if no port was found.
*/
@Override
public List<Link> getLinks(Long dpid, short port) {
List<Link> links = new ArrayList<Link>();
IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
if (srcPort == null)
return links;
ISwitchObject srcSw = srcPort.getSwitch();
if (srcSw == null)
return links;
for(IPortObject dstPort : srcPort.getLinkedPorts()) {
ISwitchObject dstSw = dstPort.getSwitch();
if (dstSw != null) {
Link link = new Link(dpid, port,
HexString.toLong(dstSw.getDPID()),
dstPort.getNumber());
links.add(link);
}
}
return links;
}
/**
* Get list of all reverse links connected to the port specified by given DPID and port number.
* @param dpid DPID of desired port.
* @param port Port number of desired port.
* @return List of reverse links. Empty list if no port was found.
*/
@Override
public List<Link> getReverseLinks(Long dpid, short port) {
List<Link> links = new ArrayList<Link>();
IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
if (srcPort == null)
return links;
ISwitchObject srcSw = srcPort.getSwitch();
if (srcSw == null)
return links;
for(IPortObject dstPort : srcPort.getReverseLinkedPorts()) {
ISwitchObject dstSw = dstPort.getSwitch();
if (dstSw != null) {
Link link = new Link(HexString.toLong(dstSw.getDPID()),
dstPort.getNumber(),
dpid, port);
links.add(link);
}
}
return links;
}
/**
* Delete records of the links connected to the port specified by given DPID and port number.
* @param dpid DPID of desired port.
* @param port Port number of desired port.
*/
@Override
public boolean deleteLinksOnPort(Long dpid, short port) {
boolean success = false;
List<Link> linksToDelete = getLinks(dpid, port);
try {
for(Link l : linksToDelete) {
if (! deleteLinkImpl(l)) {
dbop.rollback();
log.error("LinkStorageImpl:deleteLinksOnPort dpid:{} port:{} failed", dpid, port);
return false;
}
}
dbop.commit();
success = true;
} catch (Exception e) {
dbop.rollback();
e.printStackTrace();
log.error("LinkStorageImpl:deleteLinksOnPort dpid:{} port:{} failed", dpid, port);
}
return success;
}
/**
* Get list of all links connected to the switch specified by given DPID.
* @param dpid DPID of desired switch.
* @return List of links. Empty list if no port was found.
*/
@Override
public List<Link> getLinks(String dpid) {
List<Link> links = new ArrayList<Link>();
ISwitchObject srcSw = dbop.searchSwitch(dpid);
if(srcSw != null) {
for(IPortObject srcPort : srcSw.getPorts()) {
for(IPortObject dstPort : srcPort.getLinkedPorts()) {
ISwitchObject dstSw = dstPort.getSwitch();
if(dstSw != null) {
Link link = new Link(HexString.toLong(dpid),
srcPort.getNumber(),
HexString.toLong(dstSw.getDPID()),
dstPort.getNumber());
links.add(link);
}
}
}
}
return links;
}
/**
* Get list of all reverse links connected to the switch specified by
* given DPID.
* @param dpid DPID of desired switch.
* @return List of reverse links. Empty list if no port was found.
*/
@Override
public List<Link> getReverseLinks(String dpid) {
List<Link> links = new ArrayList<Link>();
ISwitchObject srcSw = dbop.searchSwitch(dpid);
if(srcSw != null) {
for(IPortObject srcPort : srcSw.getPorts()) {
for(IPortObject dstPort : srcPort.getReverseLinkedPorts()) {
ISwitchObject dstSw = dstPort.getSwitch();
if(dstSw != null) {
Link link = new Link(
HexString.toLong(dstSw.getDPID()),
dstPort.getNumber(),
HexString.toLong(dpid),
srcPort.getNumber());
links.add(link);
}
}
}
}
return links;
}
/**
* Get list of all links whose state is ACTIVE.
* @return List of active links. Empty list if no port was found.
*/
@Override
public List<Link> getActiveLinks() {
Iterable<ISwitchObject> switches = dbop.getActiveSwitches();
List<Link> links = new ArrayList<Link>();
for (ISwitchObject srcSw : switches) {
for(IPortObject srcPort : srcSw.getPorts()) {
for(IPortObject dstPort : srcPort.getLinkedPorts()) {
ISwitchObject dstSw = dstPort.getSwitch();
if(dstSw != null && dstSw.getState().equals("ACTIVE")) {
links.add(new Link(HexString.toLong(srcSw.getDPID()),
srcPort.getNumber(),
HexString.toLong(dstSw.getDPID()),
dstPort.getNumber()));
}
}
}
}
return links;
}
@Override
public LinkInfo getLinkInfo(Link link) {
// TODO implement this
return null;
}
/**
* Finalize the object.
*/
@Override
public void finalize() {
close();
}
/**
* Close LinkStorage.
*/
@Override
public void close() {
// TODO Auto-generated method stub
// graph.shutdown();
}
/**
* Update a record of link with meta-information in the LinkStorage.
* @param link Record of a link to update.
* @param linkinfo Meta-information of a link to be updated.
*/
private boolean setLinkInfoImpl(Link link, LinkInfo linkinfo) {
// TODO implement this
return false;
}
private boolean addLinkImpl(Link lt) {
boolean success = false;
IPortObject vportSrc = null, vportDst = null;
// get source port vertex
String dpid = HexString.toHexString(lt.getSrc());
short port = lt.getSrcPort();
log.debug("addLinkImpl Src dpid : {} port : {}", dpid, port);
vportSrc = dbop.searchPort(dpid, port);
// get dest port vertex
dpid = HexString.toHexString(lt.getDst());
port = lt.getDstPort();
log.debug("addLinkImpl Dst dpid : {} port : {}", dpid, port);
vportDst = dbop.searchPort(dpid, port);
log.debug("addLinkImpl vportSrc : {} vportDst : {}", vportSrc, vportDst);
if (vportSrc != null && vportDst != null) {
IPortObject portExist = null;
// check if the link exists
for (IPortObject V : vportSrc.getLinkedPorts()) {
log.debug("vportSrc.getLinkedPorts() :{}", V);
if (V.equals(vportDst)) {
portExist = V;
break;
}
}
if (portExist == null) {
vportSrc.setLinkPort(vportDst);
success = true;
} else {
log.error("LinkStorageImpl:addLinkImpl failed link exists {} {} src {} dst {}",
new Object[]{dbop, lt, vportSrc, vportDst});
}
}
return success;
}
private boolean deleteLinkImpl(Link lt) {
boolean success = false;
IPortObject vportSrc = null, vportDst = null;
// get source port vertex
String dpid = HexString.toHexString(lt.getSrc());
short port = lt.getSrcPort();
vportSrc = dbop.searchPort(dpid, port);
// get dst port vertex
dpid = HexString.toHexString(lt.getDst());
port = lt.getDstPort();
vportDst = dbop.searchPort(dpid, port);
// FIXME: This needs to remove all edges
if (vportSrc != null && vportDst != null) {
vportSrc.removeLink(vportDst);
log.debug("deleteLinkImpl(): deleted edge {} src {} dst {}", new Object[]{
lt, vportSrc, vportDst});
success = true;
}
return success;
}
}