package org.okinawaopenlabs.ofpm.business;
import static org.okinawaopenlabs.constants.ErrorMessage.*;
import static org.okinawaopenlabs.constants.OfpmDefinition.*;
import static org.okinawaopenlabs.constants.OrientDBDefinition.*;
import static org.okinawaopenlabs.constants.OfcClientDefinition.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.okinawaopenlabs.ofpm.client.OFCClient;
import org.okinawaopenlabs.ofpm.client.OFCClientImpl;
import org.okinawaopenlabs.ofpm.exception.NoRouteException;
import org.okinawaopenlabs.ofpm.exception.OFCClientException;
import org.okinawaopenlabs.ofpm.exception.ValidateException;
import org.okinawaopenlabs.ofpm.json.common.BaseResponse;
import org.okinawaopenlabs.ofpm.json.device.PortData;
import org.okinawaopenlabs.ofpm.json.ofc.InitFlowIn;
import org.okinawaopenlabs.ofpm.json.ofc.SetFlowIn;
import org.okinawaopenlabs.ofpm.json.ofc.SetFlowToOFC;
import org.okinawaopenlabs.ofpm.json.ofc.SetFlowToOFC.Action;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalLink;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopology;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopology.OfpConDeviceInfo;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopology.OfpConPortInfo;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopologyGetJsonOut;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopologyUpdateJsonIn;
import org.okinawaopenlabs.ofpm.json.topology.logical.LogicalTopologyUpdateJsonOut;
import org.okinawaopenlabs.ofpm.utils.Config;
import org.okinawaopenlabs.ofpm.utils.ConfigImpl;
import org.okinawaopenlabs.ofpm.utils.OFPMUtils;
import org.okinawaopenlabs.ofpm.validate.common.BaseValidate;
import org.okinawaopenlabs.ofpm.validate.ofc.InitFlowInValidate;
import org.okinawaopenlabs.ofpm.validate.topology.logical.LogicalTopologyValidate;
import org.okinawaopenlabs.orientdb.client.ConnectionUtilsJdbc;
import org.okinawaopenlabs.orientdb.client.ConnectionUtilsJdbcImpl;
import org.okinawaopenlabs.orientdb.client.Dao;
import org.okinawaopenlabs.orientdb.client.DaoImpl;
public class LogicalBusinessImpl implements LogicalBusiness {
private static final Logger logger = Logger.getLogger(LogicalBusinessImpl.class);
Config conf = new ConfigImpl();
Dao dao = null;
public LogicalBusinessImpl() {
if (logger.isDebugEnabled()) {
logger.debug("LogicalBusinessImpl");
}
}
/**
* Normalize nodes for update/get LogicalTopology.
* Remove node that deviceType is not SERVER or SWITCH and remove node that have no ports.
* @param conn
* @param nodes
* @throws SQLException
*/
private void normalizeLogicalNode(Connection conn, Collection<OfpConDeviceInfo> nodes) throws SQLException {
final String fname = "normalizeLogicalNode";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(conn=%s, nodes=%s) - start", fname, conn, nodes));
}
Map<String, Boolean> devTypeMap = new HashMap<String, Boolean>();
List<OfpConDeviceInfo> removalNodeList = new ArrayList<OfpConDeviceInfo>();
for (OfpConDeviceInfo node : nodes) {
String devType = node.getDeviceType();
if (!devType.equals(NODE_TYPE_SERVER) && !devType.equals(NODE_TYPE_SWITCH) && !devType.equals(NODE_TYPE_EX_SWITCH)) {
removalNodeList.add(node);
continue;
}
List<OfpConPortInfo> ports = node.getPorts();
List<OfpConPortInfo> removalPortList = new ArrayList<OfpConPortInfo>();
for (OfpConPortInfo port : ports) {
String neiDevName = port.getOfpPortLink().getDeviceName();
/* check outDevice is LEAF, other wise don't append port */
Boolean isOfpSw = devTypeMap.get(neiDevName);
if (isOfpSw == null) {
Map<String, Object> outDevDoc = dao.getNodeInfoFromDeviceName(conn, neiDevName);
String outDevType = (String)outDevDoc.get("type");
isOfpSw = OFPMUtils.isNodeTypeOfpSwitch(outDevType);
devTypeMap.put(neiDevName, isOfpSw);
}
if (!isOfpSw) {
removalPortList.add(port);
}
}
ports.removeAll(removalPortList);
/* if node don't has port that connect to leaf-switch, node remove from nodeList */
if (ports.isEmpty()) {
removalNodeList.add(node);
}
}
nodes.removeAll(removalNodeList);
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s() - end", fname));
}
}
/**
* Make node for update/get-LogicalTopology from deviceName, and return it.
* @param conn
* @param devName
* @return node for Logicaltopology.
* @throws SQLException
*/
private OfpConDeviceInfo getLogicalNode(Connection conn, String devName) throws SQLException {
final String fname = "getLogicalNode";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(conn=%s, devName=%s) - start", fname, conn, devName));
}
Map<String, Object> devDoc = dao.getNodeInfoFromDeviceName(conn, devName);
if (devDoc == null) {
return null;
}
OfpConDeviceInfo node = new OfpConDeviceInfo();
node.setDeviceName(devName);
node.setDeviceType((String)devDoc.get("type"));
node.setLocation((String)devDoc.get("location"));
node.setTenant((String)devDoc.get("tenant"));
List<OfpConPortInfo> portList = new ArrayList<OfpConPortInfo>();
List<Map<String, Object>> linkDocList = dao.getCableLinksFromDeviceName(conn, devName);
if (linkDocList == null) {
return null;
}
for (Map<String, Object> linkDoc : linkDocList) {
String outDevName = (String)linkDoc.get("outDeviceName");
PortData ofpPort = new PortData();
String outPortName = (String)linkDoc.get("outPortName");
Integer outPortNmbr = (Integer)linkDoc.get("outPortNumber");
ofpPort.setDeviceName(outDevName);
ofpPort.setPortName(outPortName);
ofpPort.setPortNumber(outPortNmbr);
String inPortName = (String)linkDoc.get("inPortName");
Integer inPortNmbr = (Integer)linkDoc.get("inPortNumber");
OfpConPortInfo port = new OfpConPortInfo();
port.setPortName(inPortName);
port.setPortNumber(inPortNmbr);
port.setOfpPortLink(ofpPort);
portList.add(port);
}
node.setPorts(portList);
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, node));
}
return node;
}
/**
* Normalize links for update/get LogicalTopology.
* Remove list that does not contains nodes.
* @param nodes
* @param links
*/
private void normalizeLogicalLink(Collection<OfpConDeviceInfo> nodes, Collection<LogicalLink> links) {
final String fname = "normalizeLogicalLink";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(nodes=%s, links=%s) - start", fname, nodes, links));
}
List<LogicalLink> removalLinks = new ArrayList<LogicalLink>();
for (LogicalLink link : links) {
List<PortData> ports = link.getLink();
if (!OFPMUtils.nodesContainsPort(nodes, ports.get(0).getDeviceName(), null)) {
removalLinks.add(link);
} else if (!OFPMUtils.nodesContainsPort(nodes, ports.get(1).getDeviceName(), null)) {
removalLinks.add(link);
}
}
links.removeAll(removalLinks);
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s() - end", fname));
}
}
/**
* Make list of link for LogicalTopology from deviceName, and return it.
* @param conn
* @param devName
* @param setPortNumber If this value is false, portNumber is every time 0.
* @return list of link for LogicalTopology.
* @throws SQLException
*/
private Set<LogicalLink> getLogicalLink(Connection conn, String devName, boolean setPortNumber) throws SQLException {
final String fname = "getLogicalLink";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(conn=%s, devName=%s, setPortNumber=%s) - start", fname, conn, devName, setPortNumber));
}
Set<LogicalLink> linkSet = new HashSet<LogicalLink>();
List<Map<String, Object>> patchDocList = dao.getLogicalLinksFromDeviceName(conn, devName);
if (patchDocList == null) {
return null;
}
/*check src->dst*/
for (Map<String, Object> patchDoc : patchDocList) {
String inDevName = (String)patchDoc.get("inDeviceName");
String inPortName = (String)patchDoc.get("inPortName");
PortData inPort = new PortData();
inPort.setDeviceName(inDevName);
inPort.setPortName(inPortName);
String outDevName = (String)patchDoc.get("outDeviceName");
String outPortName = (String)patchDoc.get("outPortName");
PortData outPort = new PortData();
outPort.setDeviceName(outDevName);
outPort.setPortName(outPortName);
List<PortData> ports = new ArrayList<PortData>();
ports.add(inPort);
ports.add(outPort);
LogicalLink link = new LogicalLink();
link.setLink(ports);
linkSet.add(link);
PortData inPort_2 = new PortData();
inPort_2.setDeviceName(outDevName);
inPort_2.setPortName(outPortName);
PortData outPort_2 = new PortData();
outPort_2.setDeviceName(inDevName);
outPort_2.setPortName(inPortName);
List<PortData> ports_2 = new ArrayList<PortData>();
ports_2.add(inPort_2);
ports_2.add(outPort_2);
LogicalLink link_2 = new LogicalLink();
link_2.setLink(ports_2);
linkSet.add(link_2);
}
if (linkSet.isEmpty()) {
return null;
}
if (!setPortNumber) {
return linkSet;
}
/* Set port number at port data in logical link */
for (LogicalLink link : linkSet) {
for (PortData port : link.getLink()) {
Map<String, Object> portMap = dao.getPortInfoFromPortName(
conn,
port.getDeviceName(),
port.getPortName());
port.setPortNumber((Integer)portMap.get("number"));
}
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, linkSet));
}
return linkSet;
}
public String getLogicalTopology(String deviceNamesCSV) {
final String fname = "getLogicalTopology";
if (logger.isDebugEnabled()) {
logger.trace(String.format("%s(deviceNames=%s) - start", fname, deviceNamesCSV));
}
LogicalTopologyGetJsonOut res = new LogicalTopologyGetJsonOut();
/* PHASE 1: Validation */
List<String> deviceNames = null;
try {
BaseValidate.checkStringBlank(deviceNamesCSV);
deviceNames = Arrays.asList(deviceNamesCSV.split(CSV_SPLIT_REGEX));
BaseValidate.checkArrayStringBlank(deviceNames);
BaseValidate.checkArrayOverlapped(deviceNames);
// TODO: check user tenant(by used-info from DMDB).
} catch (ValidateException e) {
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_BAD_REQUEST);
res.setMessage(e.getMessage());
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, res));
}
return res.toJson();
}
/* PHASE 2: Get logical topology */
ConnectionUtilsJdbc utilsJdbc = null;
Connection conn = null;
try {
utilsJdbc = new ConnectionUtilsJdbcImpl();
conn = utilsJdbc.getConnection(true);
dao = new DaoImpl(utilsJdbc);
/* Make nodes and links */
List<OfpConDeviceInfo> nodeList = new ArrayList<OfpConDeviceInfo>();
List<LogicalLink> linkList = new ArrayList<LogicalLink>();
Set<LogicalLink> linkSet = new HashSet<LogicalLink>();
for (String devName : deviceNames) {
OfpConDeviceInfo node = this.getLogicalNode(conn, devName);
if (node == null) {
continue;
}
nodeList.add(node);
Set<LogicalLink> links = this.getLogicalLink(conn, devName, true);
if (links == null) {
continue;
}
linkSet.addAll(links);
}
linkList.addAll(linkSet);
this.normalizeLogicalNode(conn, nodeList);
LogicalTopology topology = new LogicalTopology();
topology.setNodes(nodeList);
topology.setLinks(linkList);
// create response data
res.setResult(topology);
res.setStatus(STATUS_SUCCESS);
} catch (Exception e) {
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(e.getMessage());
} finally {
utilsJdbc.close(conn);
}
String ret = res.toJson();
if (logger.isDebugEnabled()) {
logger.trace(String.format("%s(ret=%s) - end", fname, ret));
}
return ret;
}
public String updateLogicalTopology(String requestedTopologyJson) {
final String fname = "updateLogicalTopology";
if (logger.isDebugEnabled()) {
logger.trace(String.format("%s(requestedTopology=%s) - start", fname, requestedTopologyJson));
}
LogicalTopologyUpdateJsonOut res = new LogicalTopologyUpdateJsonOut();
res.setStatus(STATUS_SUCCESS);
res.setResult(null);
LogicalTopologyUpdateJsonIn requestedTopology = null;
try {
requestedTopology = LogicalTopologyUpdateJsonIn.fromJson(requestedTopologyJson);
} catch (JsonSyntaxException jse) {
OFPMUtils.logErrorStackTrace(logger, jse);
res.setStatus(STATUS_BAD_REQUEST);
res.setMessage(INVALID_JSON);
String ret = res.toString();
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, ret));
}
return ret;
}
try {
LogicalTopologyValidate validator = new LogicalTopologyValidate();
validator.checkValidationRequestIn(requestedTopology);
// TODO: check user tenant (by used-info in DMDB).
} catch (ValidateException ve) {
OFPMUtils.logErrorStackTrace(logger, ve);
res.setStatus(STATUS_BAD_REQUEST);
res.setMessage(ve.getMessage());
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, res));
}
return res.toJson();
}
MultivaluedMap<String, SetFlowToOFC> reducedFlows = new MultivaluedHashMap<String, SetFlowToOFC>();
MultivaluedMap<String, SetFlowToOFC> augmentedFlows = new MultivaluedHashMap<String, SetFlowToOFC>();
ConnectionUtilsJdbc utilsJdbc = null;
Connection conn = null;
try {
/* initialize db connectors */
utilsJdbc = new ConnectionUtilsJdbcImpl();
conn = utilsJdbc.getConnection(false);
dao = new DaoImpl(utilsJdbc);
/* compute Inclement/Declement LogicalLink */
List<LogicalLink> incLinkList = new ArrayList<LogicalLink>();
List<LogicalLink> decLinkList = new ArrayList<LogicalLink>();
{
List<OfpConDeviceInfo> requestedNodes = requestedTopology.getNodes();
List<LogicalLink> requestedLinkList = requestedTopology.getLinks();
Set<LogicalLink> currentLinkList = new HashSet<LogicalLink>();
/* Create current links */
for (OfpConDeviceInfo requestedNode : requestedNodes) {
String devName = requestedNode.getDeviceName();
Set<LogicalLink> linkSet = this.getLogicalLink(conn, devName, false);
if (linkSet != null) {
currentLinkList.addAll(linkSet);
}
}
this.normalizeLogicalLink(requestedNodes, currentLinkList);
/* Set port number 0, because when run Collection.removeAll, port number remove influence. */
for (LogicalLink link : requestedLinkList) {
for (PortData port : link.getLink()) {
port.setPortNumber(null);
}
}
/* get difference between current and next */
decLinkList.addAll(currentLinkList);
decLinkList.removeAll(requestedLinkList);
incLinkList.addAll(requestedLinkList);
incLinkList.removeAll(currentLinkList);
/* sort incliment links. 1st link have port name, final link no have port name. */
Collections.sort(incLinkList, new Comparator<LogicalLink>() {
@Override
public int compare(LogicalLink link1, LogicalLink link2) {
int score1 = 0;
for (PortData port1 : link1.getLink()) {
if (StringUtils.isBlank(port1.getPortName())) {
score1++;
}
}
int score2 = 0;
for (PortData port2 : link2.getLink()) {
if (StringUtils.isBlank(port2.getPortName())) {
score2++;
}
}
return score1 - score2;
}
});
List<LogicalLink> trushIncLinkList = new ArrayList<LogicalLink>();
for (LogicalLink incLink : incLinkList) {
List<PortData> incPorts = incLink.getLink();
for (LogicalLink decLink: decLinkList) {
List<PortData> decPorts = decLink.getLink();
if (OFPMUtils.PortDataNonStrictEquals(decPorts.get(0), incPorts.get(0)) && OFPMUtils.PortDataNonStrictEquals(decPorts.get(1), incPorts.get(1))) {
decLinkList.remove(decLink);
trushIncLinkList.add(incLink);
break;
} else if (OFPMUtils.PortDataNonStrictEquals(decPorts.get(0), incPorts.get(1)) && OFPMUtils.PortDataNonStrictEquals(decPorts.get(1), incPorts.get(0))) {
decLinkList.remove(decLink);
trushIncLinkList.add(incLink);
break;
}
}
}
incLinkList.removeAll(trushIncLinkList);
}
/* update patch wiring and make patch link */
for (LogicalLink link : decLinkList) {
this.addDeclementLogicalLink(conn, link, reducedFlows);
}
for (LogicalLink link : incLinkList) {
this.addInclementLogicalLink(conn, link, augmentedFlows);
}
/* Make nodes and links */
List<LogicalLink> linkList = new ArrayList<LogicalLink>();
Set<LogicalLink> linkSet = new HashSet<LogicalLink>();
List<OfpConDeviceInfo> nodeList = requestedTopology.getNodes();
for (OfpConDeviceInfo node : nodeList) {
String devName = node.getDeviceName();
Set<LogicalLink> links = this.getLogicalLink(conn, devName, false);
if (links == null) {
continue;
}
linkSet.addAll(links);
}
linkList.addAll(linkSet);
LogicalTopology topology = new LogicalTopology();
topology.setNodes(nodeList);
topology.setLinks(linkList);
// create response data
res.setResult(topology);
utilsJdbc.commit(conn);
} catch (NoRouteException e) {
utilsJdbc.rollback(conn);
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_NOTFOUND);
res.setMessage(e.getMessage());
return res.toJson();
} catch (Exception e) {
utilsJdbc.rollback(conn);
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(e.getMessage());
return res.toJson();
} finally {
utilsJdbc.close(conn);
if (logger.isDebugEnabled()) {
logger.trace(String.format("%s(ret=%s) - end", fname, res));
}
}
/* PHASE : Set flow to OFPS via OFC */
try {
for (Entry<String, List<SetFlowToOFC>> entry : reducedFlows.entrySet()) {
OFCClient client = new OFCClientImpl();
String ofpIp = (String)entry.getKey();
for (SetFlowToOFC flow : entry.getValue()) {
client.deleteFlows(ofpIp, flow);
}
}
for (Entry<String, List<SetFlowToOFC>> entry : augmentedFlows.entrySet()) {
OFCClient client = new OFCClientImpl();
String ofpIp = (String)entry.getKey();
for (SetFlowToOFC flow : entry.getValue()) {
client.addFlows(ofpIp, flow);
}
}
} catch (OFCClientException e) {
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(e.getMessage());
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, res));
}
return res.toJson();
}
String ret = res.toJson();
if (logger.isDebugEnabled()) {
logger.trace(String.format("%s(ret=%s) - end", fname, ret));
}
return ret;
}
@Override
public String initFlow(String requestedData) {
final String fname = "initFlow";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(requestedData=%s)", fname, requestedData));
}
BaseResponse res = new BaseResponse();
res.setStatus(STATUS_SUCCESS);
/* PHASE 1: validation check */
InitFlowIn req = null;
try {
req = InitFlowIn.fromJson(requestedData);
InitFlowInValidate validator = new InitFlowInValidate();
validator.checkValidation(req);
} catch (Throwable t) {
OFPMUtils.logErrorStackTrace(logger, t);
{
if (t instanceof JsonSyntaxException) {
res.setStatus(STATUS_BAD_REQUEST);
res.setMessage(INVALID_JSON);
} else if (t instanceof ValidateException) {
res.setStatus(STATUS_BAD_REQUEST);
res.setMessage(t.getMessage());
} else {
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(t.getMessage());
}
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s)", fname, res));
}
return res.toJson();
}
/* PHASE 2:Set Flows into OFPS that is designated by datapathId. */
ConnectionUtilsJdbc utils = null;
Connection conn = null;
try {
utils = new ConnectionUtilsJdbcImpl();
conn = utils.getConnection(true);
Dao dao = new DaoImpl(utils);
String devName = dao.getDeviceNameFromDatapathId(conn, (String)req.getDatapathId());
if (null == devName) {
res.setStatus(STATUS_NOTFOUND);
res.setMessage(String.format(NOT_FOUND, (String)req.getDatapathId()));
return res.toJson();
}
Map<String, Object> devInfo = dao.getNodeInfoFromDeviceName(conn, devName);
if (null == devInfo) {
res.setStatus(STATUS_NOTFOUND);
res.setMessage(String.format(NOT_FOUND, devName));
return res.toJson();
}
Long datapathId = Long.decode((String)devInfo.get("datapathId"));
String ofcIp = (String) devInfo.get("ofcIp");
OFCClient client = new OFCClientImpl();
/* set all drop flow */
SetFlowToOFC reqData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_DROP, null, null);
client.addFlows(ofcIp, reqData);
List<Map<String, Object>> routeList = dao.getRouteFromNodeRid(conn, (String) devInfo.get("rid"));
for (Map<String, Object> route : routeList) {
Integer sequence = (Integer)route.get("sequence_num");
Integer inPortNumber = (Integer)route.get("in_port_number");
Integer outPortNumber = (Integer)route.get("out_port_number");
Map<String, Object> logicalLink = dao.getLogicalLinkFromRid(conn, (String) route.get("logical_link_id"));
Long nwInstanceId = (Long)logicalLink.get("nw_instance_id");
List<Map<String, Object>> path = dao.getRouteFromLogicalLinkId(conn, (String)route.get("logical_link_id"));
/* port 2 port flow */
if (path.size() == 1) {
SetFlowToOFC requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, inPortNumber.longValue());
client.createActionsForOutputPort(requestData, outPortNumber.longValue());
client.addFlows(ofcIp, requestData);
requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, outPortNumber.longValue());
client.createActionsForOutputPort(requestData, inPortNumber.longValue());
client.addFlows(ofcIp, requestData);
continue;
}
/* not port 2 port flow */
if (sequence == 1) {
/* first patch switch */
SetFlowToOFC requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, inPortNumber.longValue());
client.createActionsForPushVlan(requestData, outPortNumber.longValue(), nwInstanceId);
client.addFlows(ofcIp, requestData);
requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), nwInstanceId);
client.createActionsForPopVlan(requestData, inPortNumber.longValue());
client.addFlows(ofcIp, requestData);
} else if (sequence == path.size()) {
/* final patch switch */
SetFlowToOFC requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, outPortNumber.longValue());
client.createActionsForPushVlan(requestData, inPortNumber.longValue(), nwInstanceId);
client.addFlows(ofcIp, requestData);
requestData = client.createRequestData(datapathId, OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, inPortNumber.longValue(), nwInstanceId);
client.createActionsForPopVlan(requestData, outPortNumber.longValue());
client.addFlows(ofcIp, requestData);
} else {
Map<String, Object> ofpNodeDataMap = dao.getNodeInfoFromDeviceName(conn, route.get("node_name").toString());
if(ofpNodeDataMap.get("type").equals(NODE_TYPE_SPINE))
{
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, inPortNumber.longValue(), nwInstanceId);
client.createActionsForOutputPort(requestData, outPortNumber.longValue());
client.addFlows(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), nwInstanceId);
client.createActionsForOutputPort(requestData, inPortNumber.longValue());
client.addFlows(ofcIp, requestData);
}
else if(ofpNodeDataMap.get("type").equals(NODE_TYPE_AGGREGATE_SW))
{
List<Map<String,Object>> flows = null;
flows = dao.getOutertagflows(conn,(String)ofpNodeDataMap.get("datapathId"));
for(int i=0 ;i<flows.size();++i)
{
Map<String, Object> a = flows.get(i);
Long ag_inport = Long.parseLong(a.get("ag_inport").toString());
Long ag_outport = Long.parseLong(a.get("ag_outport").toString());
Long localvlan = Long.parseLong(a.get("localvlan").toString());
Long outer_tag = Long.parseLong(a.get("outer_tag").toString());
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
if(a.get("type").equals("push"))
{
client.createMatchForInPortDlVlan(requestData, ag_inport,localvlan);
client.createActionsForPushOuter_tag(requestData, ag_outport, outer_tag,localvlan);
client.addFlows(ofcIp, requestData);
}
else
{
client.createMatchForInPortDlVlan(requestData, ag_inport, outer_tag);
client.createActionsForPopOuter_tag(requestData, ag_outport);
client.addFlows(ofcIp, requestData);
}
}
}
}
}
} catch (SQLException | OFCClientException e) {
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(e.getMessage());
return res.toJson();
} catch (Exception e) {
OFPMUtils.logErrorStackTrace(logger, e);
res.setStatus(STATUS_INTERNAL_ERROR);
res.setMessage(e.getMessage());
return res.toJson();
} finally {
utils.close(conn);
String ret = res.toJson();
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s)", fname, ret));
}
}
return res.toJson();
}
/**
* Calculate new used-value when reduced patchWiring.
* @param conn
* @param link
* @param band
* @param client
* @param ofpmToken
* @return
* @throws SQLException
*/
private long calcReduceCableLinkUsed(Connection conn, Map<String, Object> link, long band) throws SQLException {
final String fname = "updateCableLinkUsed";
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(conn=%s, link=%s, band=%d) - start", fname, conn, link, band));
}
long used = (Integer)link.get("used");
long inBand = this.getBandWidth(conn, (String)link.get("inDeviceName"), (String)link.get("inPortName"));
long outBand = this.getBandWidth(conn, (String)link.get("outDeviceName"), (String)link.get("outPortName"));
long useBand = (inBand < outBand)? inBand : outBand;
used -= band;
if (used > useBand) {
used = useBand - band;
}
if (used < 0) {
used = 0;
// MEMO: output log message, however not throw exception. That's right?
logger.warn(String.format("Used value was been under than zero, and the value modify zero. %s", link));
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s(ret=%s) - end", fname, used));
}
return used;
}
/**
* Get band width from Orient DB
* @param conn
* @param deviceName
* @param portName
* @return
* @throws SQLException
*/
private long getBandWidth(Connection conn, String deviceName, String portName) throws SQLException {
long band = 0;
try {
band = Long.parseLong((String)(dao.getPortBandFromDeviceNamePortName(conn, deviceName, portName)));
} catch (NullPointerException e) {
throw new RuntimeException(String.format(NOT_FOUND, "port={deviceName:'" + deviceName + "', portName:'" + portName + "'}"));
}
return band;
}
/**
* Calc Vlan tag overhead
* @param band
* @return
*/
private long calcVlanTagOverhead(Long band) {
long bandBps = band * CONVERT_MBPS_BPS;
long maxEthFrameNum = bandBps / MIN_ETHER_FRAME_SIZE_BIT;
long vlanTagOverheadBpsPerSec = maxEthFrameNum * VLAN_FEALD_SIZE_BIT;
long ret = vlanTagOverheadBpsPerSec / CONVERT_MBPS_BPS;
return ret;
}
/**
* Delete logical link, in fact remove patch wiring and update links used value.
* @param conn
* @param link
* @throws SQLException
*/
private void addDeclementLogicalLink(Connection conn, LogicalLink link, MultivaluedMap<String, SetFlowToOFC> reducedFlows) throws SQLException {
PortData inPort = link.getLink().get(0);
/* get route */
Map<String, Object> logicalLinkMap = dao.getLogicalLinkFromNodeNamePortName(conn, inPort.getDeviceName(), inPort.getPortName());
List<Map<String, Object>> routeMapList = dao.getRouteFromLogicalLinkId(conn, (String)logicalLinkMap.get("rid"));
if (routeMapList == null || routeMapList.isEmpty()) {
throw new RuntimeException(String.format(NOT_FOUND, "route=" + link));
}
Map<String, Object> txRouteMap = routeMapList.get(0);
Map<String, Object> rxRouteMap = routeMapList.get(routeMapList.size() - 1);
/* calc patch band width */
long bandOverHead = 0L;
long band = 0L;
{
Map<String, Object> txLinkMap = dao.getCableLinkFromInPortRid(conn, (String)txRouteMap.get("in_port_id"));
Map<String, Object> rxLinkMap = dao.getCableLinkFromInPortRid(conn, (String)rxRouteMap.get("out_port_id"));
long txBand = this.getBandWidth(conn, (String)txLinkMap.get("inDeviceName"), (String)txLinkMap.get("inPortName"));
long rxBand = this.getBandWidth(conn, (String)rxLinkMap.get("inDeviceName"), (String)rxLinkMap.get("inPortName"));
long txOfpBand = this.getBandWidth(conn, (String)txLinkMap.get("outDeviceName"), (String)txLinkMap.get("outPortName"));
long rxOfpBand = this.getBandWidth(conn, (String)rxLinkMap.get("outDeviceName"), (String)rxLinkMap.get("outPortName"));
band = (txBand < rxBand) ? txBand: rxBand;
band = (band < txOfpBand)? band: txOfpBand;
band = (band < rxOfpBand)? band: rxOfpBand;
bandOverHead = this.calcVlanTagOverhead(band);
}
/* update link-used-value and make patch link for ofc */
List<String> alreadyProcCable = new ArrayList<String>();
for (Map<String, Object> routeMap : routeMapList) {
Map<String, Object> OfpsMap = dao.getNodeInfoFromDeviceName(conn, (String) routeMap.get("node_name"));
long used = band + bandOverHead;
String inPortRid = (String)routeMap.get("in_port_id");
Map<String, Object> inLink = dao.getCableLinkFromInPortRid(conn, inPortRid);
String inCableRid = (String)inLink.get("rid");
if (!alreadyProcCable.contains(inCableRid) && (OfpsMap.get("type").equals("Spine") || OfpsMap.get("type").equals("Leaf"))) {
long newUsed = this.calcReduceCableLinkUsed(conn, inLink, used);
dao.updateCableLinkUsedFromPortRid(conn, inPortRid, newUsed);
alreadyProcCable.add(inCableRid);
}
String outPortRid = (String)routeMap.get("out_port_id");
Map<String, Object> outLink = dao.getCableLinkFromOutPortRid(conn, outPortRid);
String outCableRid = (String)outLink.get("rid");
if (!alreadyProcCable.contains(outCableRid) && (OfpsMap.get("type").equals("Spine") || OfpsMap.get("type").equals("Leaf"))) {
long newUsed = this.calcReduceCableLinkUsed(conn, outLink, used);
dao.updateCableLinkUsedFromPortRid(conn, outPortRid, newUsed);
alreadyProcCable.add(outCableRid);
}
}
Map<String, Object> txOfpsMap = dao.getNodeInfoFromDeviceName(conn, (String) txRouteMap.get("node_name"));
Map<String, Object> txInPortMap = dao.getPortInfoFromPortName(conn, (String) txRouteMap.get("node_name"), (String) txRouteMap.get("in_port_name"));
Map<String, Object> txOutPortMap = dao.getPortInfoFromPortName(conn, (String) txRouteMap.get("node_name"), (String) txRouteMap.get("out_port_name"));
Map<String, Object> rxOfpsMap = dao.getNodeInfoFromDeviceName(conn, (String) rxRouteMap.get("node_name"));
Map<String, Object> rxOutPortMap = dao.getPortInfoFromPortName(conn, (String) rxRouteMap.get("node_name"), (String) rxRouteMap.get("out_port_name"));
OFCClient client = new OFCClientImpl();
if (routeMapList.size() == 1 ) {
String ofcIp = (String)txOfpsMap.get("ip") + ":" + Integer.toString((Integer)txOfpsMap.get("port"));
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)txOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
Integer inPortNumber = (Integer)txInPortMap.get("number");
client.createMatchForInPort(requestData, inPortNumber.longValue());
reducedFlows.add(ofcIp, requestData);
Integer outPortNumber = (Integer)txOutPortMap.get("number");
requestData = client.createRequestData(Long.decode((String)txOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, outPortNumber.longValue());
reducedFlows.add(ofcIp, requestData);
/* delete route */
dao.deleteRouteFromLogicalLinkRid(conn, (String)logicalLinkMap.get("rid"));
/* delete logical link */
dao.deleteLogicalLinkFromNodeNamePortName(conn, inPort.getDeviceName(), inPort.getPortName());
return;
}
/* make flow edge-switch tx side */
{
String ofcIp = (String)txOfpsMap.get("ip") + ":" + Integer.toString((Integer)txOfpsMap.get("port"));
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)txOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
Integer inPortNumber = (Integer)txInPortMap.get("number");
client.createMatchForInPort(requestData, inPortNumber.longValue());
reducedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)txOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForDlVlan(requestData, (Long)logicalLinkMap.get("nw_instance_id"));
reducedFlows.add(ofcIp, requestData);
}
/* make flow edge-switch rx side */
{
String ofcIp = (String)rxOfpsMap.get("ip") + ":" + Integer.toString((Integer)rxOfpsMap.get("port"));
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)rxOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
Integer inPortNumber = (Integer)rxOutPortMap.get("number");
client.createMatchForInPort(requestData, inPortNumber.longValue());
reducedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)rxOfpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForDlVlan(requestData, (Long)logicalLinkMap.get("nw_instance_id"));
reducedFlows.add(ofcIp, requestData);
}
/* make flow internal switch */
{
for (int i = 1; i < routeMapList.size() - 1; i++) {
String node_name = (String)routeMapList.get(i).get("node_name");
Map<String, Object> ofpsMap = dao.getNodeInfoFromDeviceName(conn, node_name);
if(ofpsMap.get("type").equals(NODE_TYPE_SPINE))
{
String ofcIp = (String)ofpsMap.get("ip") + ":" + Integer.toString((Integer)ofpsMap.get("port"));
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForDlVlan(requestData, (Long)logicalLinkMap.get("nw_instance_id"));
reducedFlows.add(ofcIp, requestData);
}
else if(ofpsMap.get("type").equals(NODE_TYPE_AGGREGATE_SW))
{
String ofcIp = (String)ofpsMap.get("ip") + ":" + Integer.toString((Integer)ofpsMap.get("port"));
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpsMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForDlVlan(requestData, (Long)logicalLinkMap.get("nw_instance_id"));
reducedFlows.add(ofcIp, requestData);
}
}
}
/* delete route */
dao.deleteRouteFromLogicalLinkRid(conn, (String)logicalLinkMap.get("rid"));
/* delete logical link */
dao.deleteLogicalLinkFromNodeNamePortName(conn, inPort.getDeviceName(), inPort.getPortName());
/* delete Outer_tag table */
//dao.DeleteOutertagflows(conn,(Long)logicalLinkMap.get("nw_instance_id"));
return;
}
/**
* Create logical link, in fact insert patch wiring, update links used value, and then notify NCS.
* @param conn
* @param link
* @param client
* @param ofpmToken
* @param augmentedFlows
* @throws SQLException
* @throws NoRouteException
*/
private void addInclementLogicalLink(Connection conn, LogicalLink link, MultivaluedMap<String, SetFlowToOFC> augmentedFlows) throws SQLException, NoRouteException {
PortData tx = link.getLink().get(0);
PortData rx = link.getLink().get(1);
/* get rid of txPort/rxPort */
String txRid = null;
String rxRid = null;
String nwid = null;
{
Map<String, Object> txMap =
(StringUtils.isBlank(tx.getPortName()))
? dao.getNodeInfoFromDeviceName(conn, tx.getDeviceName())
: dao.getPortInfoFromPortName(conn, tx.getDeviceName(), tx.getPortName());
Map<String, Object> rxMap =
(StringUtils.isBlank(rx.getPortName()))
? dao.getNodeInfoFromDeviceName(conn, rx.getDeviceName())
: dao.getPortInfoFromPortName(conn, rx.getDeviceName(), rx.getPortName());
txRid = (String)txMap.get("rid");
rxRid = (String)rxMap.get("rid");
}
Map<String, Object> txDeviceMap = dao.getNodeInfoFromDeviceName(conn, tx.getDeviceName());
Map<String, Object> rxDeviceMap = dao.getNodeInfoFromDeviceName(conn, rx.getDeviceName());
/* get shortest path */
List<Map<String, Object>> path = dao.getShortestPath(conn, txRid, rxRid);
String path_route = "";
for(int i=0;i<path.size();i++)
{
if(path.get(i).get("node_name")!=null)
{
path_route += path.get(i).get("node_name")+"("+path.get(i).get("name")+")";
if(i+1!=path.size())
{
path_route += "<->";
}
}
}
System.out.println(path_route);
//search interpoint route
String before_rid = "";
String in_spine_id = "";
String out_spine_id = "";
List<String> network = new ArrayList<String>();
for(int i=0;i<path.size();i++)
{
if(path.get(i).get("node_name")!=null)
{
Map<String,Object> route = dao.getNodeInfoFromDeviceName(conn, path.get(i).get("node_name").toString());
if(!before_rid.equals(route.get("rid").toString()))
{
if(route.get("type").toString().equals("Spine") && in_spine_id.equals(""))
{
in_spine_id = route.get("rid").toString();
}
if(route.get("type").toString().equals("Aggregate_Switch"))
{
Map<String, Object> search_network = dao.getPortInfoFromPortName(conn,path.get(i).get("node_name").toString(),path.get(i).get("name").toString());
if(search_network.get("network")!=null && !search_network.get("network").equals(""))
{
network.add(search_network.get("network").toString());
}
}
if(route.get("type").toString().equals("Spine") && !network.isEmpty())
{
out_spine_id = route.get("rid").toString();
}
}
before_rid=route.get("rid").toString();
}
}
//catch of nwid. make use of spineID from outer_tag class
if(!network.isEmpty())
{
//search of Vlanid from path.
List<Map<String, Object>> nwid1 = dao.getNetworkidFromSpineid(conn, in_spine_id, out_spine_id,network.get(0).toString());
List<Map<String, Object>> nwid2 = dao.getNetworkidFromSpineid(conn, out_spine_id, in_spine_id,network.get(0).toString());
//not asigned to vlanid from estimate path, asigned to vlanid.
if((nwid1.isEmpty() && nwid2.isEmpty()))
{
String a = network.get(0);
nwid = dao.payoutNetworkid(conn, in_spine_id, out_spine_id,a);
}
else if(!nwid1.isEmpty())
{
Map<String, Object> networkid = nwid1.get(0);
nwid = networkid.get("outer_tag").toString();
}
else if(!nwid2.isEmpty())
{
Map<String, Object> networkid = nwid2.get(0);
nwid = networkid.get("outer_tag").toString();
}
}
/* search first/last port */
int txPortIndex = (StringUtils.isBlank(tx.getPortName()))? 1: 0;
int rxPortIndex = (StringUtils.isBlank(rx.getPortName()))? path.size() - 2: path.size() - 1;
Map<String, Object> txPort = path.get(txPortIndex);
Map<String, Object> rxPort = path.get(rxPortIndex);
Map<String, Object> txPortMap = dao.getPortInfoFromPortName(conn, (String)txPort.get("node_name"), (String)txPort.get("name"));
Map<String, Object> rxPortMap = dao.getPortInfoFromPortName(conn, (String)rxPort.get("node_name"), (String)rxPort.get("name"));
/* check patch wiring exist */
{
boolean isTxPatch = dao.isContainsLogicalLinkFromDeviceNamePortName(conn, (String)txPort.get("node_name"), (String)txPort.get("name"));
boolean isRxPatch = dao.isContainsLogicalLinkFromDeviceNamePortName(conn, (String)rxPort.get("node_name"), (String)rxPort.get("name"));
if (isTxPatch || isRxPatch) {
throw new NoRouteException(String.format(IS_NO_ROUTE, (String)txPort.get("node_name") + " " + (String)txPort.get("name"), (String)rxPort.get("node_name") + " " + (String)rxPort.get("name")));
}
}
/* get band width of port info */
Map<Map<String, Object>, Long> portBandMap = new HashMap<Map<String, Object>, Long>();
for (Map<String, Object> current : path) {
if (StringUtils.equals((String)current.get("class"), "port")) {
long band = this.getBandWidth(conn, (String)current.get("node_name"), (String)current.get("name"));
portBandMap.put(current, band);
}
}
/* conmute need band-width for patching */
long needBandOverHead = 0L;
long needBand = 0L;
{
long txBand = portBandMap.get(txPort);
long rxBand = portBandMap.get(rxPort);
long txNextBand = portBandMap.get(path.get(txPortIndex + 1));
long rxNextBand = portBandMap.get(path.get(rxPortIndex - 1));
needBand = ( txBand < rxBand)? txBand: rxBand;
needBand = (needBand < txNextBand)? needBand: txNextBand;
needBand = (needBand < rxNextBand)? needBand: rxNextBand;
needBandOverHead = this.calcVlanTagOverhead(needBand);
}
/* Update links used value */
for (int i = 1; i < path.size(); i++) {
Map<String, Object> nowV = path.get(i);
Map<String, Object> prvV = path.get(i - 1);
String nowClass = (String)nowV.get("class");
String prvClass = (String)prvV.get("class");
if (!StringUtils.equals(nowClass, "port") || !StringUtils.equals(prvClass, "port")) {
continue;
}
String nowPortRid = (String)nowV.get("rid");
String nowVparentDevType = (String)nowV.get("type");
String prvVparentDevType = (String)prvV.get("type");
Map<String, Object> cableLink = dao.getCableLinkFromInPortRid(conn, nowPortRid);
long nowUsed = (Integer)cableLink.get("used");
long inBand = portBandMap.get(nowV);
long outBand = portBandMap.get(prvV);
long maxBand = (inBand < outBand)? inBand: outBand;
long newUsed = 0;
if((StringUtils.equals(nowVparentDevType, NODE_TYPE_LEAF) && StringUtils.equals(prvVparentDevType, NODE_TYPE_SPINE)) ||
(StringUtils.equals(nowVparentDevType, NODE_TYPE_SPINE) && StringUtils.equals(prvVparentDevType, NODE_TYPE_LEAF))){
//newUsed = nowUsed + needBand +needBandOverHead;
newUsed = nowUsed + needBand;
if (newUsed > maxBand) {
throw new NoRouteException(String.format(NOT_FOUND, "Path"));
}
dao.updateCableLinkUsedFromPortRid(conn, nowPortRid, newUsed);
//Add balancing to AG - Sites_SW. Balancing is Used weight only.(not check of maxBand)
} else if((StringUtils.equals(nowVparentDevType, NODE_TYPE_SITES_SW) && StringUtils.equals(prvVparentDevType, NODE_TYPE_AGGREGATE_SW)) ||
(StringUtils.equals(nowVparentDevType, NODE_TYPE_AGGREGATE_SW) && StringUtils.equals(prvVparentDevType, NODE_TYPE_SITES_SW))){
newUsed = nowUsed + needBand +needBandOverHead;
}else {
continue;
}
}
/* Make ofpatch index list */
/* MEMO: Don't integrate to the loop for the above for easy to read. */
List<Integer> ofpIndexList = new ArrayList<Integer>();
for (int i = 1; i < path.size(); i++) {
Map<String, Object> nowV = path.get(i);
String nowClass = (String)nowV.get("class");
String devType = (String)nowV.get("type");
if (!StringUtils.equals(nowClass, "node")) {
continue;
}
if (!StringUtils.equals(devType, NODE_TYPE_LEAF) && !StringUtils.equals(devType, NODE_TYPE_SPINE) && !StringUtils.equals(devType, NODE_TYPE_AGGREGATE_SW)) {
continue;
}
ofpIndexList.add(new Integer(i));
}
String nw_instance_type = NETWORK_INSTANCE_TYPE;
Long nw_instance_id = dao.getNwInstanceId(conn);
if (nw_instance_id < 0) {
throw new NoRouteException(String.format(IS_FULL, "network instance id"));
}
/* insert logical link */
dao.insertLogicalLink(conn,
(String)txDeviceMap.get("rid"),
(String)txDeviceMap.get("name"),
(String)txPortMap.get("rid"),
(String)txPortMap.get("name"),
(String)rxDeviceMap.get("rid"),
(String)rxDeviceMap.get("name"),
(String)rxPortMap.get("rid"),
(String)rxPortMap.get("name"),
nw_instance_id,
nw_instance_type);
Map<String, Object> logicalLinkMap = dao.getLogicalLinkFromNodeNamePortName(conn, (String)txDeviceMap.get("name"), (String)txPortMap.get("name"));
for (int seq = 0; seq < ofpIndexList.size(); seq++) {
int i = ofpIndexList.get(seq);
/* insert frowarding patch wiring */
Map<String, Object> inPortDataMap = path.get(i-1);
Map<String, Object> ofpPortDataMap = path.get(i);
Map<String, Object> outPortDataMap = path.get(i+1);
dao.insertRoute(
conn,
seq + 1,
(String)logicalLinkMap.get("rid"),
(String)ofpPortDataMap.get("rid"),
(String)ofpPortDataMap.get("name"),
(String)inPortDataMap.get("rid"),
(String)inPortDataMap.get("name"),
(Integer)inPortDataMap.get("number"),
(String)outPortDataMap.get("rid"),
(String)outPortDataMap.get("name"),
(Integer)outPortDataMap.get("number"));
}
/* make SetFlowToOFC list for each ofcIp */
OFCClient client = new OFCClientImpl();
/* port to port patching */
if (ofpIndexList.size() == 1) {
int i = ofpIndexList.get(0);
Map<String, Object> inPortDataMap = path.get(i - 1);
Map<String, Object> ofpNodeData = path.get(i);
Map<String, Object> ofpNodeDataMap = dao.getNodeInfoFromDeviceName(conn, (String)ofpNodeData.get("name"));
Map<String, Object> outPortDataMap = path.get(i + 1);
String ofcIp = (String)ofpNodeDataMap.get("ip") + ":" + Integer.toString((Integer)ofpNodeDataMap.get("port"));
Integer inPortNumber = (Integer)inPortDataMap.get("number");
Integer outPortNumber = (Integer)outPortDataMap.get("number");
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, inPortNumber.longValue());
client.createActionsForOutputPort(requestData, outPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, outPortNumber.longValue());
client.createActionsForOutputPort(requestData, inPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
return;
}
/* the first ofps flow */
{
int i = ofpIndexList.get(0);
Map<String, Object> inPortDataMap = path.get(i - 1);
Map<String, Object> ofpNodeData = path.get(i);
Map<String, Object> ofpNodeDataMap = dao.getNodeInfoFromDeviceName(conn, (String)ofpNodeData.get("name"));
Map<String, Object> outPortDataMap = path.get(i + 1);
String ofcIp = (String)ofpNodeDataMap.get("ip") + ":" + Integer.toString((Integer)ofpNodeDataMap.get("port"));
Integer inPortNumber = (Integer)inPortDataMap.get("number");
Integer outPortNumber = (Integer)outPortDataMap.get("number");
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, inPortNumber.longValue());
client.createActionsForPushVlan(requestData, outPortNumber.longValue(), nw_instance_id);
augmentedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), nw_instance_id);
client.createActionsForPopVlan(requestData, inPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
}
Boolean beforespinecheck = false;
/* spine ofs flow */
for (int i = 1; i < ofpIndexList.size() - 1; i++) {
/* insert frowarding patch wiring */
int index = ofpIndexList.get(i);
Map<String, Object> inPortDataMap = path.get(index-1);
Map<String, Object> ofpNodeData = path.get(index);
Map<String, Object> ofpNodeDataMap = dao.getNodeInfoFromDeviceName(conn, (String)ofpNodeData.get("name"));
Map<String, Object> outPortDataMap = path.get(index+1);
if(ofpNodeDataMap.get("type").equals("Spine"))
{
String ofcIp = (String)ofpNodeDataMap.get("ip") + ":" + Integer.toString((Integer)ofpNodeDataMap.get("port"));
Integer inPortNumber = (Integer)inPortDataMap.get("number");
Integer outPortNumber = (Integer)outPortDataMap.get("number");
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, inPortNumber.longValue(), nw_instance_id);
client.createActionsForOutputPort(requestData, outPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), nw_instance_id);
client.createActionsForOutputPort(requestData, inPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
beforespinecheck = true;
}
else if(ofpNodeDataMap.get("type").equals("Aggregate_Switch"))
{
String ofcIp = (String)ofpNodeDataMap.get("ip") + ":" + Integer.toString((Integer)ofpNodeDataMap.get("port"));
Integer inPortNumber = (Integer)inPortDataMap.get("number");
Integer outPortNumber = (Integer)outPortDataMap.get("number");
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
if(beforespinecheck.equals(true))
{
client.createMatchForInPortDlVlan(requestData, inPortNumber.longValue(),nw_instance_id);
client.createActionsForPushOuter_tag(requestData, outPortNumber.longValue(),Long.parseLong(nwid),nw_instance_id);
augmentedFlows.add(ofcIp, requestData);
dao.insertOutertag(conn,nw_instance_id.toString(),nwid,(String)ofpNodeDataMap.get("datapathId"),inPortNumber.toString(),outPortNumber.toString(),"push",network.get(0).toString());
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), Long.parseLong(nwid));
client.createActionsForPopOuter_tag(requestData, inPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
beforespinecheck = false;
dao.insertOutertag(conn,nw_instance_id.toString(),nwid,(String)ofpNodeDataMap.get("datapathId"),outPortNumber.toString(),inPortNumber.toString(),"pop",network.get(0).toString());
}
else
{
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(),nw_instance_id);
client.createActionsForPushOuter_tag(requestData, inPortNumber.longValue(), Long.parseLong(nwid),nw_instance_id);
augmentedFlows.add(ofcIp, requestData);
dao.insertOutertag(conn,nw_instance_id.toString(),nwid,(String)ofpNodeDataMap.get("datapathId"),outPortNumber.toString(),inPortNumber.toString(),"push",network.get(0).toString());
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, inPortNumber.longValue(), Long.parseLong(nwid));
client.createActionsForPopOuter_tag(requestData, outPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
dao.insertOutertag(conn,nw_instance_id.toString(),nwid,(String)ofpNodeDataMap.get("datapathId"),inPortNumber.toString(),outPortNumber.toString(),"pop",network.get(0).toString());
}
}
}
/* the final ofps flow */
{
int i = ofpIndexList.get(ofpIndexList.size() - 1);
Map<String, Object> inPortDataMap = path.get(i + 1);
Map<String, Object> ofpNodeData = path.get(i);
Map<String, Object> ofpNodeDataMap = dao.getNodeInfoFromDeviceName(conn, (String)ofpNodeData.get("name"));
Map<String, Object> outPortDataMap = path.get(i - 1);
String ofcIp = (String)ofpNodeDataMap.get("ip") + ":" + Integer.toString((Integer)ofpNodeDataMap.get("port"));
Integer inPortNumber = (Integer)inPortDataMap.get("number");
Integer outPortNumber = (Integer)outPortDataMap.get("number");
SetFlowToOFC requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPort(requestData, inPortNumber.longValue());
client.createActionsForPushVlan(requestData, outPortNumber.longValue(), nw_instance_id);
augmentedFlows.add(ofcIp, requestData);
requestData = client.createRequestData(Long.decode((String)ofpNodeDataMap.get("datapathId")), OPENFLOW_FLOWENTRY_PRIORITY_NORMAL, null, null);
client.createMatchForInPortDlVlan(requestData, outPortNumber.longValue(), nw_instance_id);
client.createActionsForPopVlan(requestData, inPortNumber.longValue());
augmentedFlows.add(ofcIp, requestData);
}
return;
}
}